姜戈 ORM。使用 AND 子句过滤多对多

Django ORM. Filter many to many with AND clause

有以下型号:

class Item(models.Model):
    name = models.CharField(max_length=255)
    attributes = models.ManyToManyField(ItemAttribute)


class ItemAttribute(models.Model):
    attribute = models.CharField(max_length=255)
    string_value = models.CharField(max_length=255)
    int_value = models.IntegerField()

我还有一个 Item,它有 2 个属性,'color': 'red''size': 3

如果我执行以下任何查询:

Item.objects.filter(attributes__string_value='red')
Item.objects.filter(attributes__int_value=3)

我会得到 Item 返回,如我所料。

但是,如果我尝试执行多个查询,例如:

Item.objects.filter(attributes__string_value='red', attributes__int_value=3)

我只想做一个 AND。这也行不通:

Item.objects.filter(Q(attributes__string_value='red') & Q(attributes__int_value=3))

输出为:

<QuerySet []>

为什么?我如何构建这样一个查询以返回我的 Item,因为它具有属性 red 和属性 3?

如果有用,您可以在 Django 中链接过滤器表达式:

query = Item.objects.filter(attributes__string_value='red').filter(attributes__int_value=3')

来自DOCS

This takes the initial QuerySet of all entries in the database, adds a filter, then an exclusion, then another filter. The final result is a QuerySet containing all entries with a headline that starts with “What”, that were published between January 30, 2005, and the current day.

要使用 .filter() 但使用动态参数:

args = {
    '{0}__{1}'.format('attributes', 'string_value'): 'red',
    '{0}__{1}'.format('attributes', 'int_value'): 3
}

Product.objects.filter(**args)

您可以(如果您需要 ANDOR 的混合)使用 Django 的 Q objects

Keyword argument queries – in filter(), etc. – are “AND”ed together. If you need to execute more complex queries (for example, queries with OR statements), you can use Q objects.

A Q object (django.db.models.Q) is an object used to encapsulate a collection of keyword arguments. These keyword arguments are specified as in “Field lookups” above.

你会得到这样的东西,而不是在那个过滤器中包含所有 Q objects

** import Q from django
from *models import Item

#assuming your arguments are kwargs
final_q_expression = Q(kwargs[1])
for arg in kwargs[2:..]
    final_q_expression = final_q_expression & Q(arg);
result = Item.objects.filter(final_q_expression)

这是我没有的代码 运行,它不在我的脑海中。如果愿意,可以将其视为伪代码。

尽管如此,这并不能回答为什么您尝试过的方法不太奏效。也许它与跨越关系 的 查找以及正在连接以获得这些值的表有关。我建议打印 yourQuerySet.query 以可视化正在形成的 raw SQL,这可能有助于指导您了解 .filter( Q() & Q()) 为何不起作用。