Holen Sie sich den letzten Datensatz in einem Abfragesatz

86

Wie kann ich den letzten Datensatz in einem bestimmten Abfragesatz abrufen?

Stephen
quelle

Antworten:

77

Sie können einfach so etwas tun, indem Sie reverse():

queryset.reverse()[0]

Beachten Sie auch diese Warnung aus der Django-Dokumentation:

... beachten Sie, dass dies reverse()im Allgemeinen nur für ein QuerySet aufgerufen werden sollte, das eine definierte Reihenfolge hat (z. B. beim Abfragen eines Modells, das eine Standardreihenfolge definiert, oder bei Verwendung order_by()). Wenn für eine bestimmte Reihenfolge keine solche Reihenfolge definiert ist QuerySet, hat das Aufrufen reverse()keine wirkliche Auswirkung (die Reihenfolge war vor dem Aufruf reverse()undefiniert und bleibt danach undefiniert).

Jujule
quelle
2
wie in django docs gesagt: "Beachten Sie, dass reverse () im Allgemeinen nur für ein QuerySet aufgerufen werden sollte, das eine definierte Reihenfolge hat (z. B. bei der Abfrage eines Modells, das eine Standardreihenfolge definiert, oder bei Verwendung von order_by ()). Wenn nein Eine solche Reihenfolge ist für ein bestimmtes QuerySet definiert. Der Aufruf von reverse () hat keine wirkliche Auswirkung (die Reihenfolge war vor dem Aufruf von reverse () undefiniert und bleibt danach undefiniert). "
Jujule
6
2017 und die akzeptierten Antworten sind jetzt veraltet. Wie unten gezeigt, sollten Sie queryset.last () verwenden.
Wobbily_col
132

Django Doc :

latest(field_name=None) Gibt das neueste Objekt in der Tabelle nach Datum zurück, wobei der Feldname als Datumsfeld verwendet wird.

In diesem Beispiel wird der neueste Eintrag in der Tabelle gemäß dem pub_dateFeld zurückgegeben:

Entry.objects.latest('pub_date')
Asinox
quelle
5
Dies ist der richtige Weg, um es zu tun. "Wenn die Meta Ihres Modells get_latest_by angibt, können Sie das Argument field_name auf latest () weglassen", wie in den Dokumenten angegeben.
Fredrik Möllerstrand
46

Der einfachste Weg ist:

books.objects.all().last()

Sie verwenden dies auch, um den ersten Eintrag wie folgt zu erhalten:

books.objects.all().first()
haky_nash
quelle
15
books.objects.last() und books.objects.first()sollte den Trick machen.
Chandan
Dies sollte die akzeptierte Antwort zusammen mit XYZ.objects.first()und XYZ.objects.last()
slajma
Ich denke, Arnaud Ps Weg ist der passendere. Wenn dies nicht falsch ist, werden alle Elemente in der Datenbank entpackt, wobei die spätere die letzte mithilfe der DB-Abfrage abruft.
Larcho
33

Django> = 1,6

QuerySet-Methoden first () und last () wurden hinzugefügt. Hierbei handelt es sich um praktische Methoden, die das erste oder letzte Objekt zurückgeben, das den Filtern entspricht. Gibt None zurück, wenn keine übereinstimmenden Objekte vorhanden sind.

Panchicore
quelle
32

So erhalten Sie das erste Objekt:

ModelName.objects.first()

So erhalten Sie die letzten Objekte:

ModelName.objects.last()

Sie können Filter verwenden

ModelName.objects.filter(name='simple').first()

Das funktioniert bei mir.

Ravi Kumar
quelle
6

Wenn der Abfragesatz bereits erschöpft ist, können Sie dies tun, um einen weiteren DB-Hinweis zu vermeiden -

last = queryset[len(queryset) - 1] if queryset else None

Nicht benutzen try...except....
Django wirft IndexErrorin diesem Fall nicht.
Es wirft AssertionErroroder ProgrammingError(wenn Sie Python mit der Option -O ausführen)

jifeng.yin
quelle
1
Angenommen, Ihr Abfragesatz ist bereits bestellt, sollte dies die "Top-Antwort" sein, da dies die einzige Lösung ist, die die Datenbank nicht erneut erreicht.
David D.
4

Wenn Sie Django 1.6 und höher verwenden, ist es jetzt viel einfacher, da die neue API eingeführt wurde -

Model.object.earliest()

Es wird spätestens () mit umgekehrter Richtung geben.

ps - Ich kenne die alte Frage. Ich poste, als ob jemand in Zukunft auf diese Frage stößt. Er lernt diese neue Funktion kennen und verwendet nicht die alte Methode.

Mutant
quelle
3
aus docs: früheste () und späteste () erfordern entweder einen Parameter field_name oder 'get_latest_by' im Modell
panchicore
1

Sie können Model.objects.last()oder verwenden Model.objects.first(). Wenn no orderingdefiniert ist, wird das Abfrageset basierend auf dem Primärschlüssel sortiert. Wenn Sie eine Abfrage zum Bestellverhalten wünschen, können Sie sich auf die letzten beiden Punkte beziehen.

Wenn Sie dies tun möchten , Model.objects.all().last()um das letzte und Model.objects.all().first()das erste Element in einem Abfragesatz abzurufen oder filtersohne einen zweiten Gedanken zu verwenden. Dann sehen Sie einige Einschränkungen unten.

Der wichtige Teil, der hier zu beachten ist, ist, dass, wenn Sie keine orderingin Ihr Modell aufgenommen haben, die Daten in beliebiger Reihenfolge vorliegen können und Sie ein zufälliges letztes oder erstes Element haben, das nicht erwartet wurde.

Z.B. Angenommen, Sie haben ein Modell Model1mit 2 Spalten idund item_count10 Zeilen mit den IDs 1 bis 10. [Es ist keine Reihenfolge definiert]

Wenn Sie Model.objects.all (). Last () wie folgt abrufen, können Sie jedes Element aus der Liste der 10 Elemente abrufen. Ja, es ist zufällig, da es keine Standardreihenfolge gibt.

Was kann man also tun?

  1. Sie können orderingbasierend auf einem beliebigen Feld oder Feldern in Ihrem Modell definieren. Es gibt auch Leistungsprobleme. Bitte überprüfen Sie dies auch. Ref: Hier
  2. ODER Sie können order_bybeim Abrufen verwenden. So was:Model.objects.order_by('item_count').last()
Roshan Dawande
quelle
-5

Der einfachste Weg, ohne sich um die aktuelle Reihenfolge kümmern zu müssen, besteht darin, das QuerySet in eine Liste zu konvertieren, damit Sie die normale negative Indizierung von Python verwenden können. Wie so:

list(User.objects.all())[-1]
Josh Ourisman
quelle
2
Dies wird ALLE Objekte aus der DB abfragen und dann das erste nehmen
warvariuc
Guter Punkt! Offensichtlich habe ich das nicht durchdacht. Die .reverse () Antwort (aktuell ausgewählt) ist der richtige Weg!
Josh Ourisman