web-dev-qa-db-de.com

Verwenden Sie die Methode get_queryset () oder setzen Sie die Variable queryset.

Diese beiden Codeteile sind beim ersten Erröten identisch:

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_poll_list'
    queryset = Poll.active.order_by('-pub_date')[:5]

und

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_poll_list'

    def get_queryset(self):
        return Poll.active.order_by('-pub_date')[:5]

Gibt es einen Unterschied zwischen ihnen? Und wenn es ist:

Welcher Ansatz ist besser? Oder wenn die Einstellung der Variable queryset besser ist, als die Methode get_queryset zu überschreiben? Und umgekehrt.

42
9Algorithm

In Ihrem Beispiel hat das Überschreiben von queryset und get_queryset die gleiche Wirkung. Ich würde die Einstellung queryset etwas bevorzugen, da dies weniger ausführlich ist.

Wenn Sie queryset einstellen, wird das Abfrageset nur einmal erstellt, wenn Sie den Server starten. Andererseits wird die get_queryset-Methode für jede Anforderung aufgerufen. 

Das bedeutet, dass get_queryset nützlich ist, wenn Sie die Abfrage dynamisch anpassen möchten. Sie können beispielsweise Objekte zurückgeben, die dem aktuellen Benutzer gehören:

class IndexView(generic.ListView):
    def get_queryset(self):
        """Returns Polls that belong to the current user"""
        return Poll.active.filter(user=self.request.user).order_by('-pub_date')[:5]

Ein anderes Beispiel, in dem get_queryset nützlich ist, ist, wenn Sie basierend auf einer aufrufbaren Funktion filtern möchten, beispielsweise die heutigen Umfragen zurückgeben:

class IndexView(generic.ListView):
    def get_queryset(self):
        """Returns Polls that were created today"""
        return Poll.active.filter(pub_date=date.today())

Wenn Sie versucht haben, dasselbe zu tun, indem Sie queryset setzen, wird date.today() nur einmal aufgerufen, wenn die Ansicht geladen wurde, und die Ansicht zeigt nach einer Weile falsche Ergebnisse.

class IndexView(generic.ListView):
    # don't do this!
    queryset = Poll.active.filter(pub_date=date.today())
60
Alasdair

Andere Antworten haben eine wichtige Implikation der Tatsache übersehen, dass das queryset-Attribut beim Start des Prozesses ausgewertet wird. Da Sie nicht nur ein Abfrageset erstellen, werden Sie tatsächlich slicing it. Dann wird die Abfrage ausgewertet . Das bedeutet, dass Sie zu diesem Zeitpunkt immer nur die Top-5-Umfragen erhalten, und diese werden nicht aktualisiert, selbst wenn Sie eine weitere erstellen, bis der Prozess neu gestartet wird.

Genau dann sollten Sie get_queryset() verwenden.

7
Daniel Roseman

Das Attribut "queryset" wird intern verwendet. Verwenden Sie immer die Methode (häufig müssen Sie benutzerdefinierte Abfragen auf der Grundlage von Request- oder Session-Variablen ausführen.

4
rj76

Modell und Abfrageset sind sehr ähnlich, der Wert von Queryset überschreibt jedoch den Wert des Modells.

Modell ist der Typ des Objekts, das diese Ansicht anzeigt.

Durch das Überschreiben von get_queryset wird gesteuert, was für spezifische Instanzen diese Ansicht angezeigt wird (Beispiel: die letzten 5 erstellten Instanzen).

Aus Djangos Dokumentation:

modell:

Das Modell, für das diese Ansicht Daten anzeigt. Die Angabe von model = Foo entspricht praktisch der Angabe von queryset = Foo.objects.all () , wobei Objekte für den Standardmanager von Foo stehen.

queryset:

Ein QuerySet, das die Objekte darstellt. Wenn angegeben, ersetzt der Wert von queryset den für model angegebenen Wert.

get_queryset:

get_queryset () Gibt das Abfrageset zurück, mit dem das Objekt abgerufen wird, das in dieser Ansicht angezeigt wird. Standardmäßig gibt get_queryset () den Wert des queryset-Attributs zurück, falls es gesetzt ist. Andernfalls erstellt es ein QuerySet, indem die all () -Methode im Standardmanager des Modellattributs aufgerufen wird.

2
Bar Horing

nur innerhalb der Klasse 

Class MyViewSet(GenericAPIView):

    queryset = ''

wenn Sie das Abfrageset nirgendwo verwenden.

Das hat bei mir funktioniert.

Vielen Dank

0
Shinto Joseph