Pobierz ostatni rekord w zestawie zapytań

89

Jak mogę pobrać ostatni rekord w określonym zestawie zapytań?

Stephen
źródło

Odpowiedzi:

81

EDYCJA: Teraz musisz użyć Entry.objects.latest('pub_date')


Możesz po prostu zrobić coś takiego, używając reverse():

queryset.reverse()[0]

Uważaj również na to ostrzeżenie w dokumentacji Django:

... zwróć uwagę, że reverse()generalnie powinno być wywoływane tylko w zestawie QuerySet, który ma zdefiniowaną kolejność (np. podczas wykonywania zapytań dotyczących modelu, który definiuje kolejność domyślną, lub podczas używania order_by()). Jeśli nie zdefiniowano takiej kolejności dla danego QuerySet, wywołanie reverse()jej nie ma rzeczywistego skutku (kolejność była niezdefiniowana przed wywołaniem reverse()i pozostanie niezdefiniowana później).

jujule
źródło
2
jak powiedziano w django docs,: "zauważ, że reverse () powinno być generalnie wywoływane tylko w QuerySet, który ma zdefiniowaną kolejność (np. podczas odpytywania modelu, który definiuje domyślną kolejność, lub podczas używania order_by ()). Jeśli nie taka kolejność jest zdefiniowana dla danego zestawu QuerySet, wywołanie reverse () na nim nie ma rzeczywistego efektu (kolejność była niezdefiniowana przed wywołaniem funkcji reverse () i pozostanie niezdefiniowana później). "
jujule
6
2017, a zaakceptowane odpowiedzi są już nieaktualne. Jak pokazano poniżej, powinieneś użyć queryset.last ().
wobbily_col
134

Django Doc :

latest(field_name=None) zwraca najnowszy obiekt w tabeli, według daty, używając pola nazwa_pola podanego jako pole daty.

Ten przykład zwraca najnowszą pozycję w tabeli, zgodnie z pub_datepolem:

Entry.objects.latest('pub_date')
Asinox
źródło
5
To jest zgrabny sposób na zrobienie tego. Ponadto, „Jeśli Meta Twojego modelu określa get_latest_by, możesz pozostawić argument field_name na latest ()” zgodnie z dokumentacją.
Fredrik Möllerstrand
50

Najprościej to zrobić:

books.objects.all().last()

Używasz tego również, aby uzyskać pierwszy wpis w ten sposób:

books.objects.all().first()
haky_nash
źródło
16
books.objects.last() i books.objects.first()powinien załatwić sprawę.
chandan
To powinna być akceptowana odpowiedź wraz z XYZ.objects.first()i XYZ.objects.last()
slajma
Myślę, że sposób Arnauda P. jest bardziej odpowiedni. To, jeśli się nie pomylisz, rozpakuje wszystkie elementy w DB, skąd później pobiera ostatnie za pomocą zapytania DB.
Larcho
33

Django> = 1.6

Dodano metody QuerySet first () i last (), które są wygodnymi metodami zwracającymi pierwszy lub ostatni obiekt pasujący do filtrów. Zwraca wartość None, jeśli nie ma pasujących obiektów.

panchicore
źródło
32

Aby zdobyć pierwszy obiekt:

ModelName.objects.first()

Aby zdobyć ostatnie obiekty:

ModelName.objects.last()

Możesz użyć filtra

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

To działa dla mnie.

Ravi Kumar
źródło
6

Gdy zestaw zapytań jest już wyczerpany, możesz to zrobić, aby uniknąć kolejnej wskazówki dotyczącej bazy danych -

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

Nie używaj try...except....
Django nie rzuca IndexErrorw tym przypadku.
Zgłasza AssertionErrorlub ProgrammingError(gdy uruchamiasz Pythona z opcją -O)

jifeng.yin
źródło
1
Zakładając, że Twój zestaw zapytań jest już uporządkowany, powinna to być „najlepsza odpowiedź”, ponieważ jest to jedyne rozwiązanie, które nie trafia ponownie do bazy danych.
David D.
4

Jeśli używasz django 1.6 i nowszych wersji, jest to teraz znacznie łatwiejsze, ponieważ wprowadzono nowy interfejs API -

Model.object.earliest()

Poda ostatnie () z odwrotnym kierunkiem.

ps - znam to stare pytanie, piszę tak, jakby idąc dalej, ktoś siada na tym pytaniu, poznaje nową funkcję i nie używa starej metody.

Mutant
źródło
3
from docs: Early () i latest () wymagają albo parametru field_name, albo 'get_latest_by' w modelu
panchicore
1

Możesz użyć Model.objects.last()lub Model.objects.first(). Jeśli nie orderingzdefiniowano wartości no, zestaw zapytań jest sortowany na podstawie klucza podstawowego. Jeśli chcesz zestaw zapytań dotyczących zachowania zamówień, możesz odwołać się do dwóch ostatnich punktów.

Jeśli myślisz o tym, Model.objects.all().last()aby pobrać ostatni i Model.objects.all().first()pobrać pierwszy element w zestawie zapytań lub użyć filtersbez namysłu. Następnie zapoznaj się z poniższymi zastrzeżeniami.

Ważną częścią, na którą należy tutaj zwrócić uwagę, jest to, że jeśli nie uwzględniłeś żadnego orderingw swoim modelu, dane mogą być w dowolnej kolejności i będziesz mieć losowy ostatni lub pierwszy element, którego nie oczekiwano.

Na przykład. Powiedzmy, że masz model o nazwie, Model1który ma 2 kolumny idi item_count10 wierszy o identyfikatorach od 1 do 10. [Nie ma zdefiniowanej kolejności]

Jeśli pobierzesz Model.objects.all (). Last () w ten sposób, możesz pobrać dowolny element z listy 10 elementów. Tak, jest losowa, ponieważ nie ma domyślnej kolejności.

Więc co można zrobić?

  1. Możesz zdefiniować orderingna podstawie dowolnego pola lub pól w modelu. Ma również problemy z wydajnością, sprawdź to również. Ref: Tutaj
  2. LUB możesz użyć order_bypodczas pobierania. Lubię to:Model.objects.order_by('item_count').last()
Roshan Dawande
źródło
-5

Najprostszym sposobem, bez martwienia się o bieżącą kolejność, jest przekonwertowanie zestawu QuerySet na listę, aby można było użyć normalnego indeksowania ujemnego Pythona. Tak jak to:

list(User.objects.all())[-1]
Josh Ourisman
źródło
2
Spowoduje to odpytanie WSZYSTKICH obiektów z bazy danych, a następnie zajmie pierwszy
warvariuc
Słuszna uwaga! Oczywiście nie przemyśleli tego. Odpowiedź .reverse () (aktualnie wybrana) jest właściwą drogą!
Josh Ourisman