Django ORM。使用AND子句过滤多对多

时间:2018-05-21 10:07:28

标签: django django-models django-orm

使用以下型号:

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

1 个答案:

答案 0 :(得分:2)

如果有任何用处,可以在Django中链接过滤表达式:

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

来自DOCS

  

这将获取数据库中所有条目的初始QuerySet,添加过滤器,然后是排除,然后是另一个过滤器。最终结果是一个QuerySet,其中包含标题以“What”开头的所有条目,这些条目是在2005年1月30日和当天之间发布的。

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

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

Product.objects.filter(**args)

您可以 (如果您需要混合使用ANDOR)使用Django&#39; s Q objects

  

关键字参数查询 - 在filter()等中 - 与“AND”编辑在一起。如果需要执行更复杂的查询(例如,带OR语句的查询),则可以使用Q对象。

     

Q对象(django.db.models.Q)是用于封装a的对象   关键字参数的集合。指定了这些关键字参数   如上面的“字段查找”。

你会有这样的东西,而不是在那个过滤器中拥有所有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())无效的原因。