Filter intermediary ManyToMany django

老子叫甜甜 提交于 2020-02-25 06:28:47

问题


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}'

I want to make two queries:

  • select all products, whose ingredients contain strawberry AND milk
  • select all products, whose ingredients contain strawberry OR milk

The first query is: Product.objects.prefetch_related('product_ingredients__ingredient').filter(product__ingredients__ingredient__name='strawberry').filter(product__ingredients__ingredient__name='milk')

Do I need to write distinct in the first query? How to write the second query?


回答1:


Do I need to write distinct in the first query?

No, or at least not if the product-ingredient combination is unique, like here. It will be distinct, since the two ingredients are clearly distinct. You furthermore should not use .prefetch_related(..) here, unless you really want to render the Product with the related Ingredients. So it is sufficient to write:

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

How to write the second query?

You can filter with an __in lookup [Django-doc]:

Product.objects.filter(
    product__ingredients__ingredient__name__in=['strawberry', 'milk']
)



回答2:


Use Q object for complex lookups

Product.objects.prefetch_related('product_ingredients__ingredient').filter(Q(product__ingredients__ingredient__name='strawberry')|Q(product__ingredients__ingredient__name='milk'))


来源:https://stackoverflow.com/questions/60225398/filter-intermediary-manytomany-django

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!