姜戈 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)
您可以也(如果您需要 AND
和 OR
的混合)使用 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())
为何不起作用。
有以下型号:
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)
您可以也(如果您需要 AND
和 OR
的混合)使用 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())
为何不起作用。