食物追踪App添加FoodLog对象时IntegrityError问题求助
问题:添加食物项时触发NOT NULL约束错误
django.db.utils.IntegrityError: NOT NULL constraint failed: accounts_foodlogfooditem.food_log_id
[23/Sep/2023 13:56:08] "POST /accounts/food-log/ HTTP/1.1" 500 153768
错误原因分析
当前视图逻辑存在两个核心问题:
- 当用户直接提交食物项表单但未选择日期(或日期表单验证失败)时,
food_log变量保持为None,赋值给food_log_food_item.food_log会触发数据库非空约束错误。 - 视图未保证处理食物项表单前,必须存在有效的
FoodLog实例,导致关联字段缺失。
修复方案
修改视图逻辑,确保只有在获取到有效FoodLog实例后,才处理食物项的保存操作,同时增加重定向避免重复提交:
from django.shortcuts import render, redirect from django.utils import timezone def food_log(request): food_log = None total_macros = {} today = timezone.now().date() if request.method == 'POST': # 通过action区分不同提交动作 action = request.POST.get('action') date_form = DateForm(request.POST) food_item_form = FoodLogFoodItemForm(request.POST) if action == 'select_date': # 处理日期选择请求 if date_form.is_valid(): selected_date = date_form.cleaned_data['date'] food_log, created = FoodLog.objects.get_or_create(user=request.user, date=selected_date) total_macros = food_log.calculate_total_macros_log() elif action == 'add_food': # 处理添加食物请求,优先从表单获取日期 if date_form.is_valid(): selected_date = date_form.cleaned_data['date'] food_log, created = FoodLog.objects.get_or_create(user=request.user, date=selected_date) else: # 日期表单无效时,默认使用当天的FoodLog food_log = FoodLog.objects.filter(user=request.user, date=today).first() # 确保FoodLog存在时再保存食物项 if food_log and food_item_form.is_valid(): food_log_food_item = food_item_form.save(commit=False) food_log_food_item.food_log = food_log food_log_food_item.save() # 重定向避免重复提交 return redirect('food_log') else: # GET请求默认加载当天的FoodLog food_log = FoodLog.objects.filter(user=request.user, date=today).first() date_form = DateForm(initial={'date': today}) if food_log: total_macros = food_log.calculate_total_macros_log() food_item_form = FoodLogFoodItemForm() return render(request, 'food_log.html', {'food_log': food_log, 'date_form': date_form, 'food_item_form': food_item_form, 'total_macros': total_macros})
模板优化建议
在模板中区分日期选择和食物添加的表单,确保提交时携带选中的日期,同时隐藏食物添加表单直到用户选择日期:
<form method="post"> {% csrf_token %} {{ date_form.as_p }} <button type="submit" name="action" value="select_date">选择日期</button> </form> {% if food_log %} <form method="post"> {% csrf_token %} <!-- 隐藏日期字段,确保提交时携带当前选中的日期 --> {{ date_form.date.as_hidden }} {{ food_item_form.as_p }} <button type="submit" name="action" value="add_food">添加食物</button> </form> <div class="macros-summary"> <h3>宏量营养总计</h3> <p>卡路里: {{ total_macros.log_total_kcal|floatformat:2 }}</p> <p>碳水化合物: {{ total_macros.log_total_carbohydrates|floatformat:2 }}g</p> <p>脂肪: {{ total_macros.log_total_fats|floatformat:2 }}g</p> <p>蛋白质: {{ total_macros.log_total_proteins|floatformat:2 }}g</p> </div> {% endif %}
内容的提问来源于stack exchange,提问作者Urek
相关产品推荐
相关产品推荐

