2016-03-09 25 views
8

W Django ORM, jak można zrobić, aby utworzyć obiekt Q, który zawsze jest fałszywy? Jest to podobne do pytania na temat always True Q objects, ale na odwrót.Zawsze Fałszywy obiekt Q

Należy pamiętać, że to nie działa:

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

Dlaczego chcę obiekt Q zamiast prostego wartość false? Tak, że można połączyć je z innymi wartościami Q, jak to na przykład:

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

Masz na myśli '.exclude (Q())'? .. – Sayse

+0

@ Sayse Widzę, jak to zadziała. Jednak chcę obiekt Q, który zawsze jest fałszywy, dzięki czemu mogę go później użyć do połączenia z innymi obiektami Q z logiką AND i OR. – Flimm

+0

Może ci pomóc, jeśli możesz pokazać [mcve] dokładnie tego, czego szukasz – Sayse

Odpowiedz

9

Co o:

Q(pk__isnull=True) 

lub

Q(pk=None) 

Wydaje hacky, ale wydaje się, aby pracować . Na przykład:

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

jednak pamiętać, że to nie działa, jak można się było spodziewać po OR'd z pustym Q().

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

Rozwiązaniem tego problemu może być użycie Q(pk__isnull=False) jako „zawsze prawdziwe 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

Należy zauważyć, że "nie działa tak, jak można by się spodziewać, gdy OR'd z pustym' Q() '" nie z powodu ograniczeń podejścia 'Q (pk = None)', ale po prostu dlatego, że 'Q() 'nie jest" prawdziwym obiektem Q ". To "pusty obiekt Q". Nie dodaje żadnych nowych informacji do systemu. Nic nie zmienia. 'Q() | [cokolwiek]' jest równoważne '[cokolwiek]'. –

+1

@LudwikTrammer to dobre wyjaśnienie, dlaczego to nie działa. Myślę więc, że rozwiązaniem może być użycie 'Q (pk__isnull = False)' zamiast 'Q()' dla 'True Q object'. – Alasdair

5

Właśnie użyłem Q(pk__in=[]) do reprezentowania tego idiomu.

Czuje się nieco mniej odrażająco i może dać optymalizatorowi DBMS nieco więcej pracy.

4

Nie mam wystarczającej reputacji, aby to skomentować, ale odpowiedź Sam Masona (Q(pk__in=[])) ma tę zaletę, że nie wykonuje nawet zapytania do bazy danych, jeśli jest używana samodzielnie. Django (v1.10) wydaje się wystarczająco inteligentny, aby rozpoznać, że warunek jest niesprawny i zwraca pusty zestaw zapytań bez zadawania bazy danych.

$ ./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

Gdy jest to tylko komentarz, nie używaj niewłaściwego przycisku odpowiedzi. Więc może chcesz poprawić nieco więcej ... aby przekształcić to w prawdziwą odpowiedź. – GhostCat

+0

Okay, ale Sam odpowiedział na to pytanie po raz pierwszy, właśnie dostałem aneks do jego odpowiedzi. Naprawdę nie wiem, co masz na myśli mówiąc "poprawić nieco więcej" - moją reputację? Moja wiedza? Chcę tylko dodać pomocną ciekawostkę, aby inni mogli skorzystać. – fwip

+0

@fwip Warto wiedzieć, dzięki! – Flimm