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)

Что я пытаюсь достичь:

  1. Get the form the user sent.
  2. 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 my models.py). After calculation is performed, save the form. (Calculation is a simple sum() 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})
Вернуться на верх