wake-up-neo.com

Wie mache ich eine ungleiche Django QuerySet-Filterung?

In Django Model QuerySets sehe ich, dass es __gt und __lt für Vergleichswerte gibt, aber es gibt __ne/!=/<> (nicht gleich?)

Ich möchte mit a ungleich herausfiltern:

Beispiel:

Model:
    bool a;
    int x;

Ich möchte

results = Model.objects.exclude(a=true, x!=5)

Der != ist nicht korrekt. Ich habe __ne, <> ausprobiert.

Ich habe folgendes benutzt:

results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)
587
MikeN

Vielleicht könnte Q Objekte bei diesem Problem hilfreich sein. Ich habe sie nie benutzt, aber es scheint, dass sie annulliert und kombiniert werden können, ähnlich wie normale python Ausdrücke.

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>, ...]
616
Dave Vogt

Ihre Abfrage scheint doppelt negativ zu sein. Sie möchten alle Zeilen ausschließen, in denen x nicht 5 ist. Mit anderen Worten, Sie möchten alle Zeilen einschließen, in denen x IS 5 ist.

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 "Ausschluss" -Methoden zur Verfügung hat, sodass Sie immer nur die logische Runde umschalten können, um das gewünschte Ergebnis zu erhalten .

544
d4nt

die Syntax field=value in Abfragen ist eine Abkürzung für field__exact=value. Das heißt, dass Django Abfrageoperatoren auf Abfragefelder in den Bezeichnern setzt. Django unterstützt die folgenden Operatoren:

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 sicher, indem ich diese mit den Q-Objekten kombiniere, wie , schlägt Dave Vogt vor und benutze filter() oder exclude() als Jason Baker schlägt vor , dass Sie genau das bekommen, was Sie für nahezu jede mögliche Abfrage benötigen.

Es ist einfach, mit Django 1.7 eine benutzerdefinierte Suche zu erstellen. Es gibt ein __ne Nachschlagebeispiel in offizielle Django-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 Suche __ne in Ihren Abfragen wie folgt verwenden:

results = Model.objects.exclude(a=True, x__ne=5)
90

In Django 1.9/1.10 gibt es drei Optionen.

  1. Chain exclude und filter

    results = Model.objects.exclude(a=true).filter(x=5)
    
  2. Verwenden Sie Q() objects und den ~ operator

    from Django.db.models import Q
    object_list = QuerySet.filter(~Q(a=True), x=5)
    
  3. Registrieren Sie eine 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
    

    Der register_lookup -Dekorator wurde in Django 1.8 hinzugefügt und ermöglicht wie gewohnt die benutzerdefinierte Suche:

    results = Model.objects.exclude(a=True, x__ne=5)
    
81
ilse2005

Bei den Modellen können Sie mit =, __gt, __gte, __lt, __lte filtern. Sie können ne, != oder <>. Mit dem Q-Objekt können Sie jedoch eine bessere Filterung erzielen.

Sie können die Verkettung von QuerySet.filter() und QuerySet.exlude() vermeiden und Folgendes verwenden:

from Django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')
40
Dami

Ausstehende Entwurfsentscheidung. Verwenden Sie in der Zwischenzeit exclude()

Der Django Issue Tracker hat den bemerkenswerten Eintrag # 576 mit dem Titel "Queryset hat keinen" ungleichen "Filteroperator" . Es ist bemerkenswert, weil es (ab April 2016) "vor 9 Jahren eröffnet" (in der Django Steinzeit), "vor 4 Jahren geschlossen" und "vor 5 Monaten zuletzt geändert" wurde.

Lesen Sie die Diskussion durch, es ist interessant. Grundsätzlich argumentieren einige Leute, dass __ne hinzugefügt werden sollte, während andere sagen, dass exclude() klarer ist, und daher __ne sollte nicht hinzugefügt werden.

(Ich stimme dem ersteren zu, da das letztere Argument in etwa der Aussage entspricht, dass Python nicht != haben sollte, weil es == und not bereits hat ...)

21
Lutz Prechelt

Sie sollten filter und exclude so verwenden

results = Model.objects.exclude(a=true).filter(x=5)
15
outoftime

Mit ausschließen und filtern

results = Model.objects.filter(x=5).exclude(a=true)
14
jincy mariam

Das letzte Codebit schließt alle Objekte aus, bei denen x! = 5 und a True ist. Versuche dies:

results = Model.objects.filter(a=False, x=5)

Denken Sie daran, dass das = -Zeichen in der obigen Zeile dem Parameter a Falsch und dem Parameter x die Zahl 5 zuweist. Es prüft nicht auf Gleichheit. Daher gibt es keine Möglichkeit, das Symbol! = In einem Abfrageaufruf zu verwenden.

8
Jason Baker

Was Sie suchen, sind alle Objekte, die entweder a=falseoderx=5 haben. In Django dient | als OR Operator zwischen Abfragesätzen:

results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
6
Gerard
results = Model.objects.filter (a = True) .exclude (x = 5)
wählen Sie * aus tablex mit a! = 0 und x! = 5
6
M. Dasn

Django-Modell-Werte (Offenlegung: Autor) liefert eine Implementierung des NotEqual -Nachschlages, wie in diese Antwort . Es bietet auch syntaktische Unterstützung dafür:

from model_values import F
Model.objects.exclude(F.x != 5, a=True)
6
A. Coady

Achten Sie auf viele falsche Antworten auf diese Frage!

Die Logik von Gerard ist korrekt, es wird jedoch eher eine Liste als ein Abfragesatz zurückgegeben (was möglicherweise keine Rolle spielt).

Wenn Sie einen Abfragesatz benötigen, verwenden Sie Q:

from Django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))
0
Mark Bailey