2014-04-02 11 views
17

Sehr oft sehe ich Konstrukte wieDjango ORM - objects.filter() vs. objects.all(). Filter() - welche wird bevorzugt?

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

, die eine QuerySet des Standard Mananger zurück. Auf den ersten all() scheint ziemlich überflüssig zu sein, weil

MyMode.objects.filter(...) 

das gleiche Ergebnis liefert.

Dies scheint jedoch nur für den Standard-Manager zu speichern, weil der beiden folgenden Anweisungen in der Dokumentation Django:

Auszug Fromt Kapitel „Hinzufügen zusätzlicher Manager-Methoden“

Eine benutzerdefinierte Manager-Methode kann alles zurückgeben, was Sie möchten. Es hat nicht, um ein QuerySet zurückzugeben.

Definition der all() Manager Methode:

alle() eine Kopie des aktuellen QuerySet Returns (oder QuerySet Unterklasse). Dies kann in Situationen nützlich sein, in denen Sie möglicherweise entweder einen Modellmanager oder ein QuerySet übergeben und weitere Filterungen für das Ergebnis durchführen möchten. Nachdem Sie alle() auf einem der Objekte aufgerufen haben, haben Sie definitiv einen QuerySet, mit dem Sie arbeiten können.

Das scheint ein bisschen wie ein Widerspruch zu mir. Auf der einen Seite bietet Django die Freiheit, eine Manager-Methode beliebig zurückgeben zu lassen, und auf der anderen Seite benötigt es ein QuerySet für die all()-Methode. Ich bin mir bewusst, dass jeder Manager eine get_queryset-Methode hat, die von all() aufgerufen wird. Aber wer hält mich davon ab, all() in meinem benutzerdefinierten Manager zu überschreiben? Obwohl ich zustimme, wäre es ein schlechtes Design, dies zu tun.

  • So soweit ich sehen kann, ist die all() Methode garantiert keine QuerySet zurückzukehren. Was genau gibt MyModel.objects zurück? Ruft diese Anweisung all() auf? oder `get_queryset()?

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

  • Haben Sie jemals wackelige Manager getroffen, die diese Methoden in einer unerwünschten Weise durcheinander bringen würden?

Antwort

33

Verfahren all() auf einem Manager nur Delegierten get_queryset(), wie Sie in den Django source code zu sehen: es ist

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

Also nur ein Weg, um die QuerySet beim Manager. Dies kann nützlich sein, um sicherzustellen, dass Sie mit einem QuerySet und nicht mit einem Manager arbeiten, da MyModel.objects einen Manager zurückgibt.

Zum Beispiel, wenn Sie über alle Elemente iterieren möchten, können Sie kann dies nicht tun:

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

Weil Sie ein Manager nicht iterieren kann. Allerdings all() die QuerySet zurückgibt, Sie können Iterierte über einen QuerySet:

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

Im Allgemeinen sollten Sie nie all() ü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, because these methods are proxied to the QuerySet. Sie müssen also nichts tun wie all().filter().

+0

Vielen Dank für mich Quellenangaben. Das hat viel erklärt. Das hat mir geholfen, Django-Anfragen viel besser zu verstehen! –

+0

Hat dies Ihre Frage beantwortet? Könnten Sie diese Antwort akzeptieren? http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – rednaw

3
  1. MyModel.objects gibt den Manager-Instanz. all() zurückgeben get_query_set(). Ich denke, alles ist da, wenn du alle Objekte brauchst.
  2. Ich bevorzuge MyModel.objects.filter() Ursache der andere ist nur eine weitere Methode aufrufen, und ich brauche nicht alle Objekte, wenn ich filtere :)
  3. Es hängt vom Zweck ab. Wenn sie jedoch eine Basismethode des Managers überschreiben, geben sie dasselbe Ergebnisformat zurück (z. B.ein QuerySet)
+1

Also die Antwort ist "' 'objects.filter()' 'ist bevorzugt, weil das Schreiben' 'all()' 'wenn Sie tatsächlich _not_ wollen nicht alle Objekte ist Python". –