2016-03-09 2 views
8

В Django ORM, как вы идете о создании объекта Q, который всегда является False?Всегда False Объект Q

Это похоже на вопрос о always True Q objects, но наоборот.

Обратите внимание, что это не работает:

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

Почему я хочу Q объект вместо простого ложного значения? Так что я могу объединить его с другими значениями 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 я могу видеть, как это будет работать. Тем не менее, я хочу, чтобы объект Q всегда был False, поэтому я могу использовать его позже для объединения с другими объектами Q с логикой AND и OR. – Flimm

+0

Это может помочь, если вы можете показать [mcve] именно то, что вы ищете – Sayse

ответ

9

насчет:

Q(pk__isnull=True) 

или

Q(pk=None) 

кажется Hacky, но это, кажется, работает , Например:

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

Однако, обратите внимание, что он не работает, как и следовало ожидать, когда OR-нут с пустым 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

Следует отметить, что «это не работает, как вы могли ожидать, когда OR'd с пустым' Q() '" не из-за ограничений подхода 'Q (pk = None)', а просто потому, что 'Q() 'не является« истинным Q-объектом ». Это «пустой объект Q». Он не добавляет никакой новой информации в систему. Это ничего не меняет. 'Q() | [все]' равнозначно '[ничего]'. –

+1

@ LudwikTrammer - это хорошее объяснение, почему это не работает. Поэтому я думаю, что возможным решением может быть использование 'Q (pk__isnull = False)' вместо 'Q()' для объекта True Q. – Alasdair

5

Я только что использовал Q(pk__in=[]), чтобы представлять эту идиому.

Чувствует себя немного менее взломанным и может дать оптимизатору СУБД немного больше для работы.

4

У меня недостаточно репутации, чтобы комментировать, но ответ Сэма Мэйсона (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

Смежные вопросы