Django UpdateView无法更新数据及消息/打印无输出问题求助
Django股票交易日志应用问题排查
我开发了一款用于股票交易记录的Django应用,作为journaling工具。用户从首页点击单条日志条目后,会进入由UpdateView处理的详情页(single_entry.html),可编辑更新条目信息或删除该条目,表单设有“保存”(对应update_button)和“删除”按钮。
目前存在两个问题:
- 删除功能正常,但更新功能原本可用现在失效,条目信息无任何变化;
messages中间件的消息无法显示在页面,print()语句也无控制台输出。
代码文件
views.py
from django.forms.models import BaseModelForm from django.shortcuts import render, redirect from django.http import HttpResponse, HttpResponseRedirect from django.views import View from django.contrib import messages from django.urls import reverse_lazy from .forms import EntryForm from .models import Entry from django.views.generic.edit import UpdateView, DeletionMixin from django.views.generic import DeleteView # Create your views here. class EntryView(View): def get(self, request): entries = Entry.objects.all().order_by("entered_date") form = EntryForm() return render(request, "entries.html", {"form":form, "entries":entries}) def post(self, request): form = EntryForm(request.POST, request.FILES) #must add request.FILES for uploads print(request.FILES) if form.is_valid(): form.save() messages.success(request, "Entry created!") return redirect("/") else: messages.error(request, "Please correct the errors below.") return render(request, "entries.html", {"form":form}) class SingleEntryView(UpdateView): template_name = "single_entry.html" model = Entry fields = ['ticker', 'strategy', 'result', 'comments', 'image'] success_url = '/' form = EntryForm def post(self, request, *args, **kwargs): if 'delete_button' in self.request.POST: self.object = self.get_object() self.object.delete() messages.success(request, "Entry has been deleted") return HttpResponseRedirect(self.get_success_url()) elif 'update_button' in self.request.POST: return super().post(request, *args, **kwargs) return redirect('/') def form_valid(self, form): form.instance.user = self.request.user return super().form_valid(form)
urls.py
from django.urls import path from django.contrib import admin from . import views urlpatterns = [ path("", views.EntryView.as_view(), name="index"), path("entries/<int:pk>/", views.SingleEntryView.as_view(), name="single-entry"), path("admin/", admin.site.urls) ]
single_entry.html
{% extends 'base.html' %} {% if messages %} <ul class="messages"> {% for message in messages %} <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %} {% block title %} Trading Journal - Entry {% endblock title %}Trading Journal {% block content %} <form method="POST" action=""> {% csrf_token %} {% for field in form %} {{field.label_tag}} {{field}} {% if field.errors %} <small class="error">{{ field.errors|striptags }}</small> {% endif %} {% endfor %} <button type="submit" name="update_button">Save</button> <button tyupe="submit" name="delete_button">Delete</button> </form> <!-- {% if entry.image.url != Null %} --> <img src="{{ entry.image.url }}" alt="{{ entry.result }}"> <!-- {% else %} --> <img src="" alt="{{ entry.result }}"> <!-- {% endif %} --> {% endblock content %}
models.py
from django.db import models from django.core.validators import MinValueValidator, MaxValueValidator from django.urls import reverse from django.utils.text import slugify class Entry(models.Model): ONEORB="1-Min ORB" FIVEORB="5-Min ORB" ABCD="ABCD" REVERSAL="Reversal" PROFIT="Profit" LOSS="Loss" RESULT_CHOICES = ( (PROFIT, "Profit"), (LOSS, "Loss") ) STRATEGY_CHOICES = ( (ONEORB,"1-Min ORB"), (FIVEORB,"5-Min ORB"), (ABCD,"ABCD"), (REVERSAL,"Reversal") ) entered_date=models.DateField(auto_now_add=True) ticker=models.CharField(max_length=8, default="") strategy=models.CharField(max_length=12, choices=STRATEGY_CHOICES, default="ONEORB") result=models.CharField(max_length=6, choices=RESULT_CHOICES, default="PROFIT") comments=models.TextField(max_length=300, blank=True) image = models.ImageField(upload_to="", null=True, blank=True) #will save to default BASE_DIR which is 'uploads' def __str__(self): return f"{self.result} {self.entered_date}"
forms.py
from django import forms from .models import Entry class EntryForm(forms.ModelForm): class Meta: model=Entry fields='__all__'
问题修复方案
1. 更新功能失效修复
你的SingleEntryView同时设置了fields和form属性,导致Django优先使用fields自动生成表单,忽略了自定义的EntryForm;另外表单未处理文件上传,缺少request.FILES传递。
修改SingleEntryView:
class SingleEntryView(UpdateView): template_name = "single_entry.html" model = Entry form_class = EntryForm # 替换原form属性为form_class success_url = '/' def post(self, request, *args, **kwargs): if 'delete_button' in request.POST: self.object = self.get_object() self.object.delete() messages.success(request, "Entry has been deleted") return HttpResponseRedirect(self.get_success_url()) elif 'update_button' in request.POST: self.object = self.get_object() # 手动传递request.FILES处理图片上传 form = self.get_form_class()(request.POST, request.FILES, instance=self.object) if form.is_valid(): return self.form_valid(form) else: return self.form_invalid(form) return redirect('/') def form_valid(self, form): # 注意:你的Entry模型没有user字段,需删除此行或给模型添加user字段 # form.instance.user = self.request.user messages.success(self.request, "Entry updated successfully!") return super().form_valid(form)
同时修改模板表单,添加文件上传必需的属性:
<form method="POST" action="" enctype="multipart/form-data">
2. Messages不显示修复
- 确保
settings.py启用了消息中间件:
MIDDLEWARE = [ # 其他中间件... 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', # 其他中间件... ]
- 确保
settings.py配置了消息存储后端:
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
- 将模板中的消息代码块移到
{% block content %}内部(base.html可能未预留外部位置):
{% block content %} {% if messages %} <ul class="messages"> {% for message in messages %} <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %} <!-- 表单代码 --> {% endblock %}
3. Print语句无输出修复
print语句的输出会出现在Django开发服务器的终端窗口中,而非浏览器控制台,查看启动runserver的那个终端即可。
内容的提问来源于stack exchange,提问作者Andre Di Carlo
相关产品推荐
相关产品推荐

