始终为假Q对象

Fli*_*imm 11 django

在Django ORM中,如何创建始终为False的Q对象?

这类似于关于始终为True Q对象的问题,但反过来说.

请注意,这不起作用:

Foobar.objects.filter(~Q()) # returns a queryset which gives all objects
Run Code Online (Sandbox Code Playgroud)

为什么我需要Q对象而不是简单的False值?这样我就可以将它与其他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()
Run Code Online (Sandbox Code Playgroud)

Ala*_*air 14

关于什么:

Q(pk__isnull=True)
Run Code Online (Sandbox Code Playgroud)

要么

Q(pk=None)
Run Code Online (Sandbox Code Playgroud)

它似乎很hacky,但它似乎工作.例如:

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

但是请注意,当使用空的OR时,它无法正常工作Q().

>>> FooBar.objects.filter(Q()|Q(pk__isnull=True))
[]
Run Code Online (Sandbox Code Playgroud)

对此的解决方案可能是使用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))
[]
Run Code Online (Sandbox Code Playgroud)

  • 应该注意的是"它没有像你想象的那样,当用空的`Q()`"进行OR运算时,不是因为`Q(pk = None)'方法的限制,而只是因为`Q( )`不是"真正的Q对象".它是"一个空的Q对象".它不会向系统添加任何新信息.它没有改变任何东西.`Q()| [anything]`等同于`[anything]`. (5认同)
  • 这个答案可能不应该被“Q(pk__in=[])”答案接受。Django 优化器(正确地)不会将“Q(pk__isnull=True)”或“Q(pk=None)”识别为始终返回空的表达式。`pk` 字段可以被覆盖,所以这不是一个安全的假设。这会导致比其他答案更混乱的查询。 (2认同)

Sam*_*son 8

我刚刚习惯Q(pk__in=[])代表这个成语.

感觉不那么hacky,并且可能会让DBMS的优化器更多地使用.


fwi*_*wip 7

我没有足够的声誉来评论,但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]: []
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,优化器将正确地简化复杂的表达式。查询 `( Q(pk__in=[]) &amp; Q(foo="bar") ) | Q(hello="world")` 会将条件简化为 `WHERE "hello" = world`。它也适用于波浪号“~”否定。 (2认同)