2016-03-09 93 views
8

在Django ORM中,如何创建一个始终为False的Q对象?总是假Q对象

这与always True Q objects的问题类似,但相反。

请注意,这并不工作:

Foobar.objects.filter(~Q()) # returns a queryset which gives all objects 

为什么我想问答对象,而不是简单的假值?所以,我可以与其他的Q值结合起来,像这样的例子:

condition = always_true_q_object 
if something_or_other: 
    condition = condition | foobar_that_returns_a_q_object() 
if something_or_other2: 
    condition = condition | foobar_that_returns_a_q_object2() 
+0

您的意思是'.exclude(Q())'?.. – Sayse

+0

@Sayse我可以看到这是如何工作的。但是,我想要一个始终为False的Q对象,以便稍后可以使用它与具有AND和OR逻辑的其他Q对象组合。 – Flimm

+0

如果你可以显示你正在寻找的是什么,它可能会有帮助 – Sayse

回答

9

什么:

Q(pk__isnull=True) 

Q(pk=None) 

似乎哈克,但它似乎工作。例如:

>>> FooBar.objects.filter(Q(x=10)|Q(pk__isnull=True)) 
[<FooBar: FooBar object>, ...] 
>>> FooBar.objects.filter(Q(x=10)&Q(pk__isnull=True)) 
[] 

但是,请注意,当与空Q()或运算的结果,你可能会想到这是行不通的。

>>> FooBar.objects.filter(Q()|Q(pk__isnull=True)) 
[] 

对此的解决方案可能是使用Q(pk__isnull=False)为“总是正确的Q”。

>>> FooBar.objects.filter(Q(pk__isnull=False)|Q(pk__isnull=True)) 
[<FooBar: FooBar object>, ...] 
>>> FooBar.objects.filter(Q(pk__isnull=False)&Q(pk__isnull=True)) 
[] 
+4

应该注意的是,“不会像'Q(pk = None)'方法的局限性那样,当你使用空'Q()'进行或运算时,它不会工作,而只是因为Q ()'不是“真正的Q对象”。这是“一个空的Q对象”。它不会向系统添加任何新信息。它不会改变任何东西。 'Q()| [任何]'等同于[[任何]]。 –

+1

@LudwikTrammer这很好的解释了为什么它不起作用。所以我认为一个可能的解决方案可能是使用'Q(pk__isnull = False)'而不是'Q()'来表示'真正的Q对象'。 – Alasdair

5

我刚刚用Q(pk__in=[])来表示这个成语。

感觉有点不太好,可能会给DBMS的优化器多一点工作。

4

我没有足够的声望发表评论,但Sam Mason的回答(Q(pk__in=[]))的优点是,如果单独使用,它甚至不会执行数据库查询。 Django(v1.10)似乎足够聪明地认识到条件不可满足,并且在不询问数据库的情况下返回一个空的查询集。

$ ./manage.py shell_plus 

In [1]: from django.db import connection 

In [2]: FooBar.objects.filter(Q(pk__in=[])) 
Out[2]: <QuerySet []> 

In [3]: connection.queries 
Out[3]: [] 
+0

当它只是一个评论,不要滥用答案按钮。所以也许你想多做点改进......把它变成真正的答案。 – GhostCat

+0

好的,但山姆先回答了问题,我刚刚回答了他的答案。我真的不知道你的意思是“提高一点点” - 我的声誉?我的知识?我只是想添加一个有用的小知识,以便其他人可以受益。 – fwip

+0

@fwip知道这真的很有用,谢谢! – Flimm