Django - Модель формы с ManyToManyField - как вычислить поле?
В моем views.py
есть такой код:
from django.shortcuts import render
from .helpers import *
from .forms import OrderForm
def create_order(request):
if request.method == 'POST':
form = OrderForm(request.POST)
if not request.POST._mutable:
request.POST._mutable = True
if form.is_valid():
obj = form.save(commit=False)
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.
"""
prices_of_ordered_foods = obj.ordered_foods
print(prices_of_ordered_foods)
return sum(prices_of_ordered_foods)
Что я пытаюсь достичь:
- Get the form the user sent.
- Calculate field
total_price
based on the prices of chosen meals/foods by the user when he was filling up the forms (this is a ManyToManyField in mymodels.py
). After calculation is performed, save the form. (Calculation is a simplesum()
method.)
However, this does not work. I am getting this error: <MyOrderObject> needs to have a value for field "id" before this many-to-many relationship can be used.
Есть идеи, как это исправить?
Спасибо
Вы не можете использовать сигнал post_save
, посланный Order.save
, для вычисления total_price
, поскольку только после вызова метода save
устанавливаются отношения "многие-ко-многим". Поэтому необходимо сохранить экземпляр Order, назначить блюда/продукты и только после этого вызвать calculate_total_price_obj
.
def create_order(request):
if request.method == 'POST':
form = OrderForm(request.POST)
if not request.POST._mutable:
request.POST._mutable = True
if form.is_valid():
obj = form.save(commit=True)
# Note that you must set many-to-many relationships before calling calculate_total_price_obj
obj.total_price = calculate_total_price_obj(obj)
obj.save()
else:
form = OrderForm()
return render(request, 'create_order.html', {'form': form})