Django ModelForm含ManyToManyField场景下如何计算订单总价
问题原因
- Django的多对多字段依赖主表的主键ID才能建立关联,你调用
calculate_total_price_obj的时候,obj还未执行数据库写入操作,没有生成id值,无法读取多对多关联的餐品数据 - 调用
form.save(commit=False)之后,表单内的多对多数据不会自动写入数据库,需要手动调用form.save_m2m()完成多对多关联数据的保存 - 现有
calculate_total_price_obj逻辑错误,obj.ordered_foods是Django的多对多管理器对象,不是餐品的价格列表,不能直接求和 - 你修改
request.POST._mutable的代码没有实际作用,可直接删除
修复代码
修改后views.py
from django.shortcuts import render from .helpers import calculate_total_price_obj from .forms import OrderForm def create_order(request): if request.method == 'POST': form = OrderForm(request.POST) if form.is_valid(): # 先保存基础字段到数据库,生成主键ID obj = form.save(commit=False) obj.save() # 保存多对多关联的餐品数据 form.save_m2m() # 计算总价后二次保存订单 obj.total_price = calculate_total_price_obj(obj) obj.save() else: form = OrderForm() return render(request, 'create_order.html', {'form': form})
修改后helpers.py
普通遍历版本:
def calculate_total_price_obj(obj) -> float: """ Calculate the total_price of the order. This function has to be called after the Order has been created and saved. """ return sum(food.price for food in obj.ordered_foods.all())
更高性能的数据库聚合版本(推荐):
from django.db.models import Sum def calculate_total_price_obj(obj) -> float: return obj.ordered_foods.aggregate(total=Sum('price'))['total'] or 0.0
内容的提问来源于stack exchange,提问作者neisor
相关产品推荐
相关产品推荐

