如何在Django中实现重复鸡体重记录的覆盖确认功能
解决方案
问题分析
你当前的实现存在两个核心问题:
- 重复确认页面的表单未携带用户输入的体重数据,点击"Overwrite"后无法获取要覆盖的数值
- 视图函数中缺少处理覆盖确认请求的逻辑分支
具体修改步骤
1. 更新视图函数,传递用户输入的体重并处理覆盖请求
修改views.py中的add_record函数,在捕获重复错误时保存用户输入的体重,同时新增处理覆盖POST请求的逻辑:
# views.py from django.http import Http404, HttpResponseRedirect from django.shortcuts import redirect, render from .models import Chicken, Record from .forms import RecordForm from datetime import datetime def add_record(request, chicken) -> HttpResponseRedirect | HttpResponse: """ View for the "record_weight.html" Post & Get methods """ if request.method == "POST": # 处理覆盖确认的请求 if request.POST.get('overwrite') == 'yes': chicken_obj = Chicken.objects.filter(number=chicken).first() if not chicken_obj: raise Http404("Bird does not exist") # 获取用户之前输入的体重和日期 new_weight = request.POST.get('weight') record_date = datetime.now().date() # 找到当天的旧记录并更新 old_record = Record.objects.filter(chicken=chicken_obj, date=record_date).first() if old_record: old_record.weight = new_weight old_record.save() return redirect("/admin/tags/record/") # 处理初始的体重提交请求 form = RecordForm(request.POST) if form.is_valid(): record = form.save(commit=False) record.chicken = Chicken.objects.filter(number=chicken).first() record.date = datetime.now().date() try: Record.save(record) except ValidationError: # 传递用户输入的体重到确认页面 return render(request, "tags/duplicate_record.html", { "bird": record.chicken, "new_weight": record.weight # 把用户输入的体重传过去 }) return redirect("/admin/tags/record/") form = RecordForm() try: birds = Chicken.objects.all() req_bird = birds.filter(number=chicken).first() except Chicken.DoesNotExist: raise Http404("Bird does not exist") req_records = Record.objects.filter(chicken_id=chicken).order_by("-date") # 简化倒序写法 return render(request, "tags/record_weight.html", { "bird": req_bird, "records": req_records, "form": form, "nav_filter": get_birds_navbar(birds) })
2. 修改确认页面表单,携带体重数据并使用POST请求
更新duplicate_record.html,把表单改成POST方法,用隐藏字段保存新体重,同时调整按钮逻辑:
# duplicate_records.html (styling removed for easier reading) {% extends "tags/layout.html" %} {% block content %} <div> <div> <h2>There is already a weight for today!</h2> <p>Do you want to overwrite that entry with the new weight: {{ new_weight }}?</p> <form method="POST"> {% csrf_token %} <!-- 隐藏字段保存新体重和覆盖标识 --> <input type="hidden" name="weight" value="{{ new_weight }}"> <input type="hidden" name="overwrite" value="yes"> <a href="/records/{{ bird.number }}">No</a> <button type="submit">Overwrite</button> </form> </div> </div> {% endblock %}
3. 确保模型层的唯一约束正确
你的Record模型需要有针对chicken和date的唯一约束,示例如下:
# models.py from django.db import models class Record(models.Model): chicken = models.ForeignKey(Chicken, on_delete=models.CASCADE) date = models.DateField() weight = models.DecimalField(max_digits=5, decimal_places=2) class Meta: unique_together = ('chicken', 'date') # 确保同一只鸡同一天只有一条记录
这样当用户提交重复记录时,Record.save()会抛出ValidationError,触发确认流程。
逻辑说明
- 用户提交体重后,如果当天已有记录,视图捕获
ValidationError,将用户输入的体重传递到确认页面 - 确认页面显示新体重,表单通过POST请求携带体重数据和覆盖标识
- 视图收到覆盖请求后,找到当天的旧记录并更新体重,完成覆盖操作
内容的提问来源于stack exchange,提问作者quietCoder
相关产品推荐
相关产品推荐

