Фильтр-посредник ManyToMany django - PullRequest
1 голос
/ 14 февраля 2020
class Ingredient(Model):
    name = CharField(max_length=55, unique=True)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('name',)



class Product(Model):
    name = CharField(max_length=55)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('name', )


class ProductIngredient(Model):
    product = ForeignKey(Product, on_delete=CASCADE, related_name='product_ingredients')
    ingredient = ForeignKey(Ingredient, on_delete=CASCADE)
    optional = BooleanField(default=False)

    class Meta:
        unique_together = (('product', 'ingredient'),)
        ordering = ('product__name',)

    def __str__(self):
        return f'{self.product} - {self.ingredient}'

Я хочу сделать два запроса:

  • выбрать все продукты, в состав которых входят клубника И молоко
  • выбрать все продукты, в состав которых входят клубника ИЛИ молоко

Первый запрос: Product.objects.prefetch_related('product_ingredients__ingredient').filter(product__ingredients__ingredient__name='strawberry').filter(product__ingredients__ingredient__name='milk')

Нужно ли писать distinct в первом запросе? Как написать второй запрос?

Ответы [ 2 ]

2 голосов
/ 14 февраля 2020

Нужно ли писать отличительные в первом запросе?

Нет или, по крайней мере, если комбинация product - ingredient уникальна , как здесь. Это будет отличаться, так как эти два компонента явно различны. Кроме того, вам не следует использовать .prefetch_related(..) здесь, если вы действительно не хотите рендерить Product с соответствующими Ingredient s. Поэтому достаточно написать:

Product.objects.filter(
    product__ingredients__ingredient__name='strawberry'
).filter(
    product__ingredients__ingredient__name='milk'
)

Как написать второй запрос?

Вы можете фильтровать с помощью __in lookup [Django -doc] :

Product.objects.filter(
    <b>product__ingredients__ingredient__name__in=['strawberry', 'milk']</b>
)
2 голосов
/ 14 февраля 2020

Используйте Q объект для сложных поисков

Product.objects.prefetch_related('product_ingredients__ingredient').filter(Q(product__ingredients__ingredient__name='strawberry')|Q(product__ingredients__ingredient__name='milk'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...