【问题标题】:Django ORM. Filter many to many with AND clauseDjango ORM。使用 AND 子句过滤多对多
【发布时间】:2018-05-21 10:07:27
【问题描述】:

具有以下型号:

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,它有两个属性,'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 django-models django-orm


【解决方案1】:

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

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

来自DOCS

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

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

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

Product.objects.filter(**args)

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

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

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

您将拥有类似这样的东西,而不是在该过滤器中包含所有 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() &amp; Q()) 为何不起作用。

【讨论】:

    猜你喜欢
    • 2020-06-06
    • 1970-01-01
    • 2016-09-05
    • 2021-07-07
    • 2020-12-13
    • 2019-09-08
    • 1970-01-01
    • 2011-05-29
    • 2020-08-04
    相关资源
    最近更新 更多