Skip to main content
 首页 » 编程设计

python之Django ORM AND-在 ManyToMany 上查找

2024年09月07日33zhujiabin

如何在同一字段的 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') 

然而,当创建更复杂的查询时,Q1、Q2、Q3 是 Q() 对象,然后

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 查询不适用于 ManyToMany 关系。

请您参考如下方法:

过滤器 已经是一个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)