Как выполнить __all_in запрос в Django?
У меня есть три модели
class Pizza(models.Model):
    toppings = models.ManyToManyField(Topping)
class Topping(models.Model):
    name = models.CharField(max_length=50)
class Order(models.Model):
    must_have_toppings = models.ManyToManyField(Topping)
Я хочу найти все заказы, которые соответствуют определенной пицце. Для этого я хотел бы сделать что-то вроде
orders = Order.objects.filter(must_have_toppings__all_in=my_pizza.toppings)
Что я пробовал:
orders = Order.objects.filter(must_have_toppings__in=my_pizza.toppings) не работает, потому что будут возвращены заказы с одним из начинок пиццы в их must_have.
И:
orders = Orders.objects
for topping in my_pizza.toppings.all():
    orders = orders.filter(must_have_toppings=topping)
 не работает, потому что он вернет заказы, в которых есть все начинки из пиццы, даже если некоторые из must_have_toppings отсутствуют. Например, пицца с помидорами и грибами вернет заказ, в котором нужны помидоры, перец и грибы.
Как я могу искать заказы, в которых обязательные_элементы есть ВСЕ в объекте Pizza?
(я использую MySql)
Если вы хотите найти заказы, где все Topping в заказе принадлежат my_pizza, мы можем отфильтровать с помощью:
from django.db.models import F, Q
toppings = my_pizza.toppings.all()
Order.objects.annotate(
    ntoppings=Count(
        'must_have_toppings',
        filter=Q(must_have_toppings__in=toppings)
    ),
    total=Count('must_have_toppings')
).filter(
    ntoppings=F('total')
) Сначала мы получаем все топпинги из my_pizza, а затем проверяем, совпадает ли количество топпингов i с количеством топпингов, принадлежащих my_pizza, если да, то мы знаем, что все топпинги заказа являются членами этой пиццы.
Мы также можем сделать наоборот и проверить, все ли начинки my_pizza принадлежат Order:
from django.db.models import Count, Q
toppings = my_pizza.toppings.all()
ntoppings = len(toppings)
Order.objects.annotate(
    ntoppings=Count(
        'must_have_toppings',
        filter=Q(must_have_toppings__in=toppings)
    )
).filter(
    ntoppings=ntoppings
) Если в заказе Order больше начинок, чем в пицце, то этот заказ все равно будет отображаться. Так, если пицца имеет в качестве начинки сыр и ананас, то заказ с сыром, салями и ананасом будет соответствовать.
 Для точного совпадения, когда заказ и my_pizza имеют одинаковые начинки, мы можем работать с:
from django.db.models import Count, Q
toppings = my_pizza.toppings.all()
ntoppings = len(toppings)
Order.objects.annotate(
    ntoppings=Count(
        'must_have_toppings',
        filter=Q(must_have_toppings__in=toppings)
    ),
    total=Count('must_have_toppings')
).filter(
    ntoppings=ntoppings,
    total=ntoppings
)Все фрагменты кода предполагают, что топпинг может произойти только один раз.