Na przykładzie możesz zobaczyć filtr wielu zapytań OR:
Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
Na przykład skutkuje to:
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
Jednak chcę utworzyć ten filtr kwerendy z listy. Jak to zrobić?
na przykład [1, 2, 3] -> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
Article.objects.filter(pk__in=[1, 2, 3])
użyłbyś w nowoczesnym django, ale pytanie jest nadal aktualne, jeśli chcesz zrobić coś bardziej zaawansowanego, wykonując razem OR'owanie obiektów Q.Odpowiedzi:
Możesz połączyć swoje zapytania w następujący sposób:
źródło
Aby zbudować bardziej złożone zapytania, istnieje również opcja użycia wbudowanych w Q () stałych obiektu Q.OR i Q.AND wraz z metodą add () w następujący sposób:
źródło
q_objects |= Q(pk=item)
list
się, że jest pusty, zwrócisz równowartośćArticle.objects.all()
. Łatwo jednak złagodzić, wracającArticle.objects.none()
do tego testu.q_objects
pomocąQ(id__in=[])
. Zawsze kończy się niepowodzeniem, chyba że zostanie z czymś poddany OR, a optymalizator zapytań ładnie to obsłuży.Krótszy sposób napisania odpowiedzi Dave'a Webba za pomocą funkcji redukuj w Pythonie :
źródło
functools.reduce
. źródłooperator.or_
zamiast lambdy.źródło
operator
wzięło?Może lepiej jest użyć instrukcji sql IN.
Zobacz informacje o API queryset .
Jeśli naprawdę potrzebujesz tworzyć zapytania z dynamiczną logiką, możesz zrobić coś takiego (brzydkie + nie przetestowane):
źródło
query |= Q(field=cond)
Zobacz dokumentację :
Zwróć uwagę, że ta metoda działa tylko w przypadku wyszukiwania klucza podstawowego, ale wydaje się, że to jest to, co próbujesz zrobić.
Więc chcesz:
źródło
W przypadku, gdy chcemy programowo ustawić, o które pole db chcemy zapytać:
źródło
Rozwiązanie wykorzystujące
reduce
ior_
operatory do filtrowania przez mnożenie pól.ps
f
to nowy literał łańcuchów formatu. Został wprowadzony w Pythonie 3.6źródło
Za pomocą operatora | = można programowo aktualizować zapytanie przy użyciu obiektów Q.
źródło
Ten jest dla dynamicznej listy pk:
źródło
q = Q()
zamiastq = None
, a następnie usunąćif q is None
klauzulę - nieco mniej wydajne, ale możesz usunąć trzy wiersze kodu. (Puste Q jest następnie łączone, gdy zapytanie jest uruchamiane).Inna opcja nie była świadoma do niedawna -
QuerySet
również nadpisuje&
,|
,~
, etc, operatorów. Inne odpowiedzi, że obiekty OR Q są lepszym rozwiązaniem na to pytanie, ale ze względu na zainteresowanie / argumentację możesz zrobić:str(q.query)
zwróci jedno zapytanie ze wszystkimi filtrami wWHERE
klauzuli.źródło
Dla pętli:
Redukować:
Oba są równoważne
Article.objects.filter(pk__in=values)
Ważne jest, aby rozważyć, czego chcesz, gdy
values
jest pusty. Wiele odpowiedzi zQ()
wartością początkową zwróci wszystko .Q(pk__in=[])
to lepsza wartość początkowa. Jest to zawsze zawodzący obiekt Q, który jest dobrze obsługiwany przez optymalizator (nawet w przypadku złożonych równań).Jeśli chcesz zwrócić wszystko, gdy
values
jest puste, powinieneś ORAZ z,~Q(pk__in=[])
aby zapewnić to zachowanie:Należy pamiętać, że
Q()
to nic , nie zawsze kolejny obiekt Q. Każda operacja z tym związana po prostu całkowicie go upuści.źródło
easy ..
from django.db.models import Q import you model args = (Q (visibility = 1) | (Q (visibility = 0) & Q (user = self.user))) #Tuple parameters = {} #dic order = limit „create_at” = 10
źródło