In einem Beispiel sehen Sie einen Mehrfach-ODER-Abfragefilter:
Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
Dies führt beispielsweise zu:
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
Ich möchte diesen Abfragefilter jedoch aus einer Liste erstellen. Wie geht das?
z.B [1, 2, 3] -> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
Article.objects.filter(pk__in=[1, 2, 3])
im modernen Django verwenden, aber die Frage ist immer noch relevant, wenn Sie etwas weiter fortgeschrittenes tun möchten, indem Sie Q-Objekte zusammenfügen.Antworten:
Sie können Ihre Abfragen wie folgt verketten:
quelle
Um komplexere Abfragen zu erstellen, besteht auch die Möglichkeit, die Konstanten Q.OR und Q.AND des eingebauten Q () -Objekts zusammen mit der add () -Methode wie folgt zu verwenden:
quelle
q_objects |= Q(pk=item)
list
es leer ist, das Äquivalent von zurückgebenArticle.objects.all()
. Leicht zu entschärfenArticle.objects.none()
, wenn Sie für diesen Test zurückkehren.q_objects
mitQ(id__in=[])
. Es wird immer fehlschlagen, es sei denn, mit etwas ODER-verknüpft und das Abfrageoptimierungsprogramm wird es gut handhaben.Eine kürzere Art, Dave Webbs Antwort mit der Reduktionsfunktion von Python zu schreiben :
quelle
functools.reduce
. Quelleoperator.or_
anstelle des Lambda zu verwenden.quelle
operator
?Vielleicht ist es besser, die SQL IN-Anweisung zu verwenden.
Siehe Queryset-API-Referenz .
Wenn Sie wirklich Abfragen mit dynamischer Logik durchführen müssen, können Sie Folgendes tun (hässlich + nicht getestet):
quelle
query |= Q(field=cond)
Siehe die Dokumente :
Beachten Sie, dass diese Methode nur für die Suche nach Primärschlüsseln funktioniert. Dies scheint jedoch das zu sein, was Sie versuchen.
Was Sie also wollen, ist:
quelle
Falls wir programmgesteuert festlegen möchten, welches Datenbankfeld wir abfragen möchten:
quelle
Lösung, die
reduce
undor_
Operatoren zum Filtern nach Multiplikationsfeldern verwendet.ps
f
ist ein neues Format für Zeichenfolgenliteral. Es wurde in Python 3.6 eingeführtquelle
Mit dem Operator | = können Sie eine Abfrage mithilfe von Q-Objekten programmgesteuert aktualisieren.
quelle
Dieser ist für dynamische pk Liste:
quelle
q = Q()
stattdessenq = None
dieif q is None
Klausel verwenden und dann entfernen - etwas weniger effizient, aber drei Codezeilen entfernen. (Das leere Q wird anschließend zusammengeführt, wenn die Abfrage ausgeführt wird.)Eine andere Möglichkeit war ich nicht bewusst , bis vor kurzem -
QuerySet
auch außer Kraft setzt&
,|
,~
usw, Betreiber. Die anderen Antworten, dass OR Q-Objekte eine bessere Lösung für diese Frage sind, aber aus Gründen des Interesses / der Argumentation können Sie Folgendes tun:str(q.query)
gibt eine Abfrage mit allen Filtern in derWHERE
Klausel zurück.quelle
For-Schleife:
Reduzieren:
Beide sind gleichbedeutend mit
Article.objects.filter(pk__in=values)
Es ist wichtig zu überlegen, was Sie wollen, wenn
values
es leer ist. Viele Antworten mitQ()
als Startwert geben alles zurück .Q(pk__in=[])
ist ein besserer Startwert. Es ist ein immer fehlerhaftes Q-Objekt, das vom Optimierer gut verarbeitet wird (auch bei komplexen Gleichungen).Wenn Sie alles zurückgeben möchten , wenn
values
es leer ist, sollten Sie UND mit~Q(pk__in=[])
, um dieses Verhalten sicherzustellen:Es ist wichtig , sich daran zu erinnern , dass
Q()
ist nichts , kein Immer nachfolgenden Q - Objekt. Bei jeder Operation wird es einfach vollständig gelöscht.quelle
einfach ..
aus django.db.models importieren Q importieren Sie Modell args = (Q (Sichtbarkeit = 1) | (Q (Sichtbarkeit = 0) & Q (Benutzer = self.user))) #Tuple parameters = {} #dic order = 'create_at' limit = 10
quelle