Я думаю, что, вероятно, не хорошая идея сделать это. Может быть много причин, по которым меняется отношение «многие ко многим». Будет очень трудно или даже невозможно охватить все это. Например, сам объект Topping
может быть удален, и, следовательно, может вызвать изменение во всех отношениях «многие ко многим», в которых использовалась начинка. Кроме того, в Django ORM есть некоторые функции, такие как .bulk_create(..)
[Django-doc] и .update(..)
[Django-doc] , которыеобойти сигнальный механизм Django и, таким образом, может привести базу данных в несогласованное состояние. Поэтому может иметь смысл просто удалить поле has_toppings
:
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
# <i>no</i> has_toppings
Возможно, имеет смысл просто аннотировать ваши Pizza
наборы запросов. Например, с помощью:
from django.db.models import Exists, OuterRef
Pizza.objects.annotate(
has_toppings=Exists(
<b>Pizza.toppings.through.objects.filter(pizza_id=OuterRef('pk'))</b>
)
)
Это сгенерирует запрос, который выглядит следующим образом:
SELECT pizza.id,
<b>EXISTS(</b>
SELECT U0.id, U0.pizza_id, U0.topping_id
FROM pizza_toppings U0
WHERE U0.pizza_id = pizza.id
<b>) AS has_toppings</b>
FROM pizza
Этот набор запросов можно использовать при доступе к Pizza.objects
, установив менеджер:
from django.db.models import Exists, OuterRef
class <b>PizzaManager</b>(models.Manager):
def get_queryset(self):
return Pizza.objects.annotate(
has_toppings=Exists(
Pizza.toppings.through.objects.filter(pizza_id=OuterRef('pk'))
)
)
class Topping(models.Model):
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
<b>objects = PizzaManager()</b>
Так что теперь мы можем, например, получить все Pizza
s с начинками с:
Pizza.objects.filter(<b>has_toppings=True</b>)