Wie mache ich eine nicht gleiche in Django Queryset -Filterung?
-
22-08-2019 - |
Frage
In Django Model Querysets sehe ich, dass es eine gibt __gt
und __lt
Für Vergleichswerte, gibt es aber a __ne
/!=
/<>
(nicht gleich?)
Ich möchte mit einem nicht gleichwertigen herausfiltern:
Beispiel:
Model:
bool a;
int x;
Ich will
results = Model.objects.exclude(a=true, x!=5)
Das !=
ist keine korrekte Syntax. Ich habe es versucht __ne
, <>
.
Am Ende verwendete ich:
results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)
Lösung
Vielleicht Q Objekte könnte für dieses Problem hilfreich sein. Ich habe sie nie benutzt, aber es scheint, dass sie negiert und ähnlich wie normale Python -Ausdrücke kombiniert werden können.
Update: Ich habe es gerade ausprobiert, es scheint ziemlich gut zu funktionieren:
>>> from myapp.models import Entry
>>> from django.db.models import Q
>>> Entry.objects.filter(~Q(id = 3))
[<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...]
Andere Tipps
Ihre Abfrage scheint ein doppeltes Negativ zu haben. Sie möchten alle Zeilen ausschließen, in denen X nicht 5 ist. Mit anderen Worten, Sie möchten alle Zeilen einbeziehen, in denen X 5 ist. Ich glaube, dies wird den Trick tun.
results = Model.objects.filter(x=5).exclude(a=true)
Um Ihre spezifische Frage zu beantworten, gibt es kein "Nicht gleich", aber das liegt wahrscheinlich daran, dass Django sowohl "Filter" als auch "ausschließen" Methoden zur Verfügung hat, damit Sie immer die Logikrunde wechseln können, um das gewünschte Ergebnis zu erzielen.
das field=value
Syntax in Abfragen ist eine Abkürzung für field__exact=value
. Das heißt das Django stellt Abfragebetreiber auf Abfragefelder in die Kennungen ein. Django unterstützt die folgenden Betreiber:
exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex
Ich bin mir sicher, indem ich diese mit den Q -Objekten kombiniere als Dave Vogt schlägt vor und verwenden filter()
oder exclude()
wie Jason Baker schlägt vor Sie erhalten genau das, was Sie für eine mögliche Abfrage benötigen.
Es ist einfach, mit Django 1.7 einen benutzerdefinierten Lookup zu erstellen. Dort ist ein __ne
Suchbeispiel in Django Offizielle Dokumentation.
Sie müssen zuerst die Suche selbst erstellen:
from django.db.models import Lookup
class NotEqual(Lookup):
lookup_name = 'ne'
def as_sql(self, qn, connection):
lhs, lhs_params = self.process_lhs(qn, connection)
rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params
return '%s <> %s' % (lhs, rhs), params
Dann müssen Sie es registrieren:
from django.db.models.fields import Field
Field.register_lookup(NotEqual)
Und jetzt können Sie die verwenden __ne
Suchen Sie in Ihren Abfragen wie folgt:
results = Model.objects.exclude(a=True, x__ne=5)
Im Django 1.9/1.10 Es gibt drei Optionen.
-
results = Model.objects.exclude(a=true).filter(x=5)
Verwenden
Q()
Objekte und die~
Operatorfrom django.db.models import Q object_list = QuerySet.filter(~Q(a=True), x=5)
Registrieren a benutzerdefinierte Suchfunktion
from django.db.models import Lookup from django.db.models.fields import Field @Field.register_lookup class NotEqual(Lookup): lookup_name = 'ne' def as_sql(self, compiler, connection): lhs, lhs_params = self.process_lhs(compiler, connection) rhs, rhs_params = self.process_rhs(compiler, connection) params = lhs_params + rhs_params return '%s <> %s' % (lhs, rhs), params
Das
register_lookup
Dekorateur wurde hinzugefügt in Django 1.8 und ermöglicht eine benutzerdefinierte Suche wie gewohnt:results = Model.objects.exclude(a=True, x__ne=5)
Während der Modelle können Sie mit filtern =
, __gt
, __gte
, __lt
, __lte
, Sie können nicht verwenden ne
, !=
oder <>
. Sie können jedoch eine bessere Filterung bei der Verwendung des Q -Objekts erreichen.
Sie können es vermeiden, zu werden QuerySet.filter()
und QuerySet.exlude()
, und verwenden Sie dies:
from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')
Ausstehende Entwurfsentscheidung. In der Zwischenzeit verwenden Sie exclude()
Der Django -Ausgabe -Tracker hat das bemerkenswerte Eintrag Nr. 5763, mit dem Titel "QuerySet hat keinen" nicht gleichen "Filteroperator". Es ist bemerkenswert, weil es (ab April 2016) "vor 9 Jahren eröffnet wurde" (in der Django Stone Age), "vor 4 Jahren geschlossen" und "Letzte vor 5 Monaten".
Lesen Sie die Diskussion durch, es ist interessant. Grundsätzlich argumentieren einige Leute __ne
sollte hinzugefügt werden, während andere sagen exclude()
ist klarer und daher __ne
sollte nicht hinzugefügt werden.
(Ich stimme erstere zu, weil das letztere Argument ungefähr gleichbedeutend mit der Aussage von Python ist !=
Weil es hat ==
und not
schon...)
Du solltest benutzen filter
und exclude
so was
results = Model.objects.exclude(a=true).filter(x=5)
Verwenden von Ausschluss und Filter
results = Model.objects.filter(x=5).exclude(a=true)
Das letzte Stück Code schließt alle Objekte aus, bei denen x! = 5 und a wahr sind. Versuche dies:
results = Model.objects.filter(a=False, x=5)
Denken Sie daran, dass das = in der obigen Zeile dem Parameter A und der Nummer 5 dem Parameter x False zugewiesen wird. Es geht nicht um Gleichheit. Daher gibt es also keine Möglichkeit, das Symbol in einem Abfrageanruf zu verwenden.
Was Sie suchen, sind alle Objekte, die entweder haben a=false
oder x=5
. In Django, |
dient als OR
Bediener zwischen QuerySets:
results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
results = Model.objects.filter(a = True).exclude(x = 5)Generiert diese SQL:
select * from tablex where a != 0 and x !=5Das SQL hängt davon ab, wie Ihr wahres/falsches Feld dargestellt wird, und der Datenbankmotor. Der Django -Code ist alles, was Sie brauchen.
Django-model-values (disclosure: author) provides an implementation of the NotEqual lookup, as in this answer. It also provides syntactic support for it:
from model_values import F
Model.objects.exclude(F.x != 5, a=True)
Watch out for lots of incorrect answers to this question!
Gerard's logic is correct, though it will return a list rather than a queryset (which might not matter).
If you need a queryset, use Q:
from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))