Oft möchte ich das erste Objekt aus einem Abfragesatz in Django holen oder zurückkehren, None
wenn es keine gibt. Es gibt viele Möglichkeiten, die alle funktionieren. Aber ich frage mich, welches am performantesten ist.
qs = MyModel.objects.filter(blah = blah)
if qs.count() > 0:
return qs[0]
else:
return None
Führt dies zu zwei Datenbankaufrufen? Das scheint verschwenderisch. Geht das schneller?
qs = MyModel.objects.filter(blah = blah)
if len(qs) > 0:
return qs[0]
else:
return None
Eine andere Option wäre:
qs = MyModel.objects.filter(blah = blah)
try:
return qs[0]
except IndexError:
return None
Dies erzeugt einen einzelnen Datenbankaufruf, was gut ist. Es ist jedoch erforderlich, häufig ein Ausnahmeobjekt zu erstellen. Dies ist sehr speicherintensiv, wenn Sie nur einen trivialen Wenn-Test benötigen.
Wie kann ich dies mit nur einem einzigen Datenbankaufruf tun, ohne den Speicher mit Ausnahmeobjekten zu belasten?
len()
Gedanken über die Minimierung von DB- Roundtrips machen, verwenden Sie diese nicht für Abfragesätze, sondern immer.count()
.first()
undlast()
bequemen Methoden hinzugefügt : docs.djangoproject.com/en/dev/ref/models/querysets/#firstAntworten:
Django 1.6 (veröffentlicht November 2013) eingeführt , um die Bequemlichkeit Methoden
first()
undlast()
die schlucken die resultierende Ausnahme und Rückkehr ,None
wenn die queryset keine Objekte zurückgibt.quelle
first()
undlast()
eine DurchsetzungORDER BY
Klausel auf einer Abfrage. Dadurch werden die Ergebnisse deterministisch, die Abfrage wird jedoch höchstwahrscheinlich verlangsamt.Die richtige Antwort ist
Welches kann verwendet werden in:
Sie möchten es nicht zuerst in eine Liste umwandeln, da dies einen vollständigen Datenbankaufruf aller Datensätze erzwingen würde. Tun Sie einfach das oben genannte und es wird nur das erste ziehen. Sie können sogar
.order_by
sicherstellen, dass Sie das erste erhalten, das Sie möchten..get()
Stellen Sie sicher, dass Sie das hinzufügen, sonst erhalten Sie ein QuerySet zurück und kein Objekt.quelle
Entry.objects.all()[0]
?quelle
LIMIT 1
der Abfrage hinzugefügt wird , und ich weiß nicht, dass Sie es besser machen können. Intern__nonzero__
inQuerySet
wird jedochtry: iter(self).next() except StopIteration: return false...
so implementiert, dass es der Ausnahme nicht entgeht.QuerySet.__nonzero__()
wird nie aufgerufen, da das vor der Überprüfung auf RichtigkeitQuerySet
in alist
konvertiert wird. Andere Ausnahmen können jedoch weiterhin auftreten.StopIteration
Ausnahme erzeugen .__iter__
, um ein neues Iteratorobjekt abzurufen und dessennext
Methode aufzurufen , bisStopIteration
ausgelöst wird. Also definitiv wird es irgendwo eine Ausnahme geben;)In Django 1.9 haben Sie jetzt eine
first()
Methode für Abfragesätze.Dies ist ein besserer Weg als
.get()
oder[0]
weil es keine Ausnahme auslöst, wenn das Abfrageset leer ist. Daher müssen Sie die Verwendung nicht überprüfenexists()
quelle
Wenn Sie vorhaben, das erste Element häufig zu erhalten, können Sie QuerySet in folgende Richtung erweitern:
Definieren Sie das Modell folgendermaßen:
Und benutze es so:
quelle
Dies könnte auch funktionieren:
Wenn es leer ist, wird eine leere Liste zurückgegeben, andernfalls wird das erste Element in einer Liste zurückgegeben.
quelle
Es kann so sein
oder
quelle
Sie sollten Django-Methoden verwenden, wie sie existieren. Es ist für Sie da, um es zu benutzen.
quelle
Seit django 1.6 können Sie filter () mit der first () -Methode wie folgt verwenden:
quelle