Django表单提交后表格数据不显示问题求助
Django股票交易记录应用表单提交后条目不显示问题修复
问题描述
我开发了一款股票交易记录简易应用,在Entry模型中实现了基于仓位、开盘价和收盘价计算盈亏(pnl)的功能。代码能正常执行并将正确的pnl值保存到数据库,但表单提交后,新条目无法在entries.html的表格中显示——只有点击浏览器返回按钮才会出现,手动刷新页面也无效,甚至所有条目都仅在点击返回后才显示。我尝试注释掉给pnl值上色的main.js代码,问题仍未解决。
相关代码
entries.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 {% endblock title %}Trading Journal {% block content %} <form method="POST" enctype="multipart/form-data" action="/"> {% csrf_token %} {{ form }} <button>Submit</button> </form> {% endblock content %} {% block table %} <table class="blueTable sortable"> <thead> <tr> <th>Date</th> <th>Ticker</th> <th>Strategy</th> <th>Result</th> <th>Open Price</th> <th>Position</th> <th>Closed Price</th> <th>P&L</th> <th>Comments</th> </tr> </thead> <tfoot> <tr> <td colspan="9"> <div class="links"><a href="#">«</a> <a class="active" href="#">1</a> <a href="#">2</a> <a href="#">3</a> <a href="#">4</a> <a href="#">»</a></div> </td> </tr> </tfoot> <tbody> {% for entry in entries %} <tr> <td><a href="{% url 'single-entry' entry.id %}">{{entry.entered_date}}</a></td><td>{{entry.ticker}}</td><td>{{entry.strategy}}</td><td>{{entry.result}}</td><td>{{entry.open_price}}</td><td>{{entry.position}}</td><td>{{entry.close_price}}</td><td class="entry_pnl">{{entry.pnl}}</td><td>{{entry.comments}}</td></tr> {% endfor %} </tbody> </tr> </table> {% if request.user.is_authenticated %} <a href="{% url 'logout' %}"><button>Logout</button></a> {% endif %} {% endblock table %}
Views.py(负责显示条目表格及新增表单)
class EntryView(LoginRequiredMixin, View): login_url = 'login' def get(self, request): logged_in_user = request.user.id print("****************") print(f'Logged in user:{logged_in_user}') entries = Entry.objects.filter(trader_id=logged_in_user).order_by("entered_date") form = EntryForm() return render(request, "entries.html", {"form":form, "entries":entries, "user":logged_in_user}) def post(self, request): form = EntryForm(request.POST, request.FILES) if form.is_valid(): form.instance.trader = request.user form.instance.calculate_pnl() form.save() print('***************') print(f"Entry pnl:{form.instance.pnl}") return render(request, "entries.html") else: messages.error(request, "Please correct the errors below.") return render(request, "entries.html", {"form":form})
Models.py
from django.db import models from django.core.validators import MinValueValidator, MaxValueValidator from django.urls import reverse from django.contrib.auth.models import User 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) position = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1)], blank=True, null=True) open_price = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True) close_price = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True) pnl = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True) trader = models.ForeignKey(User, on_delete=models.CASCADE, blank=False, related_name="entries") def calculate_pnl(self): self.pnl = round(self.position * self.close_price - self.position * self.open_price, 2) def __str__(self): return f"{self.result} {self.entered_date}"
main.js
document.addEventListener('DOMContentLoaded', function() { let displayObj = document.querySelectorAll('.entry_pnl'); displayObj.forEach(function(el) { let pnlValue = parseFloat(el.innerText); if(pnlValue < 0) { el.style.color = 'red'; } else { el.style.color = 'green'; } }); });
问题分析
核心问题在EntryView的post方法中:
- 表单验证通过保存后,直接调用
render返回页面,但没有传递entries数据,模板中的{% for entry in entries %}因无数据不渲染表格内容 - 直接返回渲染页面会让浏览器保留POST请求状态,刷新时会触发重复提交提示,且无法获取最新的条目列表
修复方案
1. 修改post方法,表单有效时重定向到GET请求
替换原post方法中表单有效时的返回逻辑,用redirect触发当前视图的GET请求,重新获取最新条目:
def post(self, request): form = EntryForm(request.POST, request.FILES) if form.is_valid(): form.instance.trader = request.user form.instance.calculate_pnl() form.save() print('***************') print(f"Entry pnl:{form.instance.pnl}") # 重定向到当前路径,触发GET请求加载最新数据 return redirect(request.path) else: messages.error(request, "Please correct the errors below.") # 表单无效时也要传递entries,避免表格为空 logged_in_user = request.user.id entries = Entry.objects.filter(trader_id=logged_in_user).order_by("entered_date") return render(request, "entries.html", {"form":form, "entries":entries})
2. 可选优化:自动计算pnl
将calculate_pnl整合到模型的save方法中,无需手动调用:
def save(self, *args, **kwargs): if self.position and self.open_price and self.close_price: self.pnl = round(self.position * self.close_price - self.position * self.open_price, 2) super().save(*args, **kwargs)
这样调用form.save()时会自动计算pnl,可删除form.instance.calculate_pnl()这行代码。
内容的提问来源于stack exchange,提问作者Andre Di Carlo
相关产品推荐
相关产品推荐

