webentwicklung-frage-antwort-db.com.de

Django ORM - objects.filter () vs. objects.all (). Filter () - welches wird bevorzugt?

Sehr oft sehe ich Konstrukte wie

MyModel.objects.all().filter(...)

dadurch wird ein QuerySet des Standardmanagers zurückgegeben. Zunächst scheint all() ziemlich redundant zu sein, weil

MyMode.objects.filter(...)

liefert das gleiche Ergebnis.

Dies scheint jedoch nur für den Standard-Manager sicher zu sein, da die folgenden beiden Anweisungen in der Django Dokumentation enthalten sind:

Auszug aus dem Kapitel "Zusätzliche Manager-Methoden hinzufügen"

Eine benutzerdefinierte Manager-Methode kann alles zurückgeben, was Sie möchten. Es muss kein QuerySet zurückgegeben werden.

Definition der all() Manager Methode:

all () Gibt eine Kopie des aktuellen QuerySet (oder der aktuellen QuerySet-Unterklasse) zurück. Dies kann in Situationen nützlich sein, in denen Sie möglicherweise einen Modellmanager oder ein QuerySet übergeben und das Ergebnis weiter filtern möchten. Nachdem Sie all () für ein Objekt aufgerufen haben, müssen Sie definitiv mit einem QuerySet arbeiten.

Das scheint mir ein bisschen ein Widerspruch zu sein. Einerseits bietet Django) die Freiheit, eine Manager-Methode den von Ihnen bevorzugten Objekttyp zurückgeben zu lassen, andererseits erfordert sie ein QuerySet für die all()-Methode Beachten Sie, dass jeder Manager eine get_queryset - Methode hat, die von all() aufgerufen wird. Aber wer hindert mich daran, all() in meinem benutzerdefinierten Manager zu überschreiben? Design, um dies zu tun.

  • Soweit ich sehen kann, garantiert die all() -Methode nicht, dass ein QuerySet zurückgegeben wird. Was genau gibt MyModel.objects Zurück? Ruft diese Anweisung all() auf? oder `get_queryset ()?

  • Bevorzugen Sie MyModel.objects.filter(...) oder MyModel.objects.all().filter(...)? Und wenn ja, warum?

  • Haben Sie jemals Wonky-Manager getroffen, die sich auf unerwünschte Weise mit diesen Methoden herumschlagen würden?

37
Dr.Elch

Die Methode all() eines Managers delegiert nur an get_queryset(), wie Sie im Django-Quellcode sehen können :

def all(self):
    return self.get_queryset()

Es ist also nur eine Möglichkeit, das QuerySet vom Manager abzurufen. Dies kann nützlich sein, um sicherzustellen, dass es sich um ein QuerySet und nicht um einen Manager handelt, da MyModel.objects Einen Manager zurückgibt.

Wenn Sie beispielsweise alle Elemente durchlaufen möchten, können Sie nicht :

for item in MyModel.objects:
    # do something with item

Weil Sie nicht über einen Manager iterieren können. Jedoch gibt all() das QuerySet zurück, Sie können über ein QuerySet iterieren:

for item in MyModel.objects.all():
    # do something with item

Im Allgemeinen sollten Sie all() niemals überschreiben. Sie können get_queryset() überschreiben, aber diese Methode muss ein QuerySet zurückgeben.

Wenn Sie eine Filtermethode wie filter() oder exclude() verwenden würden, hätten Sie bereits das QuerySet, weil diese Methoden an das QuerySet weitergeleitet werden . Sie müssen also nicht so etwas wie all().filter() tun.

50
gitaarik
  1. MyModel.objects Gibt die Manager-Instanz zurück. all() return get_query_set(). Ich denke, alles ist da, wenn Sie alle Objekte benötigen.
  2. Ich bevorzuge MyModel.objects.filter(), weil der andere nur ein weiterer Methodenaufruf ist und ich nicht alle Objekte benötige, wenn ich filtere :)
  3. Es kommt auf den Zweck an. Wenn sie jedoch eine Basismethode des Managers überschreiben, geben sie dasselbe Ergebnisformat zurück (z. B. ein QuerySet).

Mymodel.objects.filter(username='abcd') gibt eine Liste der Übereinstimmungsdatensätze aus. Mymodel.objects.get(pk='abcd') gibt einen einzelnen Datensatz mit Übereinstimmung für den Primärschlüsselwert zurück

0
aarif faridi