当前位置: 代码迷 >> python >> 多对多上的 Django ORM AND-lookups
  详细解决方案

多对多上的 Django ORM AND-lookups

热度:113   发布时间:2023-07-16 11:23:20.0

如何在同一字段的 Q() 上实现 AND 查找。

class Foo(models.Model):
    name = models.ManyToManyField(Type)

class Type(models.Model):
    type = models.CharField()

我试过:

Foo.objects.filter(Q(name__type='any'), Q(name__type='some'))

Foo.objects.filter(Q(name__type='any') & Q(name__type='some'))

然而,它们都提供空的查询集。

我知道,这会起作用:

Foo.objects.filter(name__type='any').filter(name__type='some')

但是,当创建更复杂的查询时,其中Q1Q2Q3Q()对象然后

Foo.objects.filter(Q1).filter(Q2).filter(Q3)

可以提供不同的结果

Foo.objects.filter(Q2).filter(Q3).filter(Q1)

由于应用过滤器的顺序。

更新:我意识到这个 AND 查询有效,因为 modelField 不是ManyToMany而是CharField

Type.objects.filter(Q(type__icontains='some') & Q(type__icontains='thing'))

因此,仅进行 AND-Query 对多对多关系不起作用。

filter已经是一个AND查找。 通常你会想要使用Q()查询来组合OR查找。 我这么说是因为使用AND查找还有其他方法来组成动态查询。

预计以下查询将返回一个空的查询集:

Foo.objects.filter(Q(name__type='any') & Q(name__type='some'))

因为Type实例被命名为“any”或“some”——它不能同时被命名,所以查询集将始终为空。

但是语法是正确的。 您可以使用它来连接多个AND查找表达式(只要它们过滤不同的字段,否则您最终可能会得到一个空的查询集)。 因为过滤器应用于数据库中的每一行。

创建复杂和动态过滤器(使用AND查找)的另一种方法是使用字典:

params = {
  'first_name': 'foo',
  'last_name': 'bar'
}

if condition:
    params['email'] = 'foo@bar.com'

Foo.objects.filter(**params)

正如Victor Freitas已经解释过的那样,一个字段在同一个记录中不可能有两个值,但是由于你的关系是多对多的,所以可以有多个记录,因此这两个值可以存在对于同一字段,但要进行此查询,您必须使用 OR 运算符:

Foo.objects.filter(Q(name__type='any') | Q(name__type='some'))