Obtenha o último registro em um queryset

89

Como posso recuperar o último registro de um determinado queryset?

Stephen
fonte

Respostas:

81

EDIT: agora você tem que usar Entry.objects.latest('pub_date')


Você poderia simplesmente fazer algo assim, usando reverse():

queryset.reverse()[0]

Além disso, tome cuidado com este aviso da documentação do Django:

... note que reverse()geralmente só deve ser chamado em um QuerySet que tem uma ordem definida (por exemplo, ao consultar um modelo que define uma ordem padrão, ou ao usar order_by()). Se nenhuma ordem for definida para um dado QuerySet, chamá reverse()-lo não tem efeito real (a ordem era indefinida antes da chamada reverse()e permanecerá indefinida depois).

Jujule
fonte
2
como dito na documentação do django,: "note que reverse () geralmente só deve ser chamado em um QuerySet que tem uma ordem definida (por exemplo, ao consultar um modelo que define uma ordem padrão, ou ao usar order_by ()). Se não tal ordenação é definida para um determinado QuerySet, chamar reverse () nele não tem efeito real (a ordenação era indefinida antes de chamar reverse () e permanecerá indefinida depois). "
julho
6
2017 e as respostas aceitas estão desatualizadas. Conforme mostrado abaixo, você deve usar queryset.last ().
wobbily_col
137

Django Doc :

latest(field_name=None) retorna o objeto mais recente na tabela, por data, usando o field_name fornecido como o campo de data.

Este exemplo retorna a última entrada na tabela, de acordo com o pub_datecampo:

Entry.objects.latest('pub_date')
Asinox
fonte
5
Esta é a maneira legal de fazer isso. Além disso, "Se o Meta do seu modelo especifica get_latest_by, você pode deixar de fora o argumento field_name para o mais recente ()" de acordo com os documentos.
Fredrik Möllerstrand
51

A maneira mais simples de fazer isso é:

books.objects.all().last()

Você também pode usar isso para obter a primeira entrada, como:

books.objects.all().first()
haky_nash
fonte
16
books.objects.last() e books.objects.first()deve fazer o truque.
chandan
Esta deve ser a resposta aceita junto com XYZ.objects.first()e XYZ.objects.last()
slajma
Acho que o jeito de Arnaud P é o mais adequado. Isso se não for engano vai descompactar todos os itens no banco de dados onde o último puxa o último usando a consulta do banco de dados.
Larcho
33

Django> = 1,6

Adicionados os métodos QuerySet first () e last (), que são métodos de conveniência que retornam o primeiro ou o último objeto correspondente aos filtros. Retorna Nenhum se não houver nenhum objeto correspondente.

Panchicore
fonte
32

Para obter o primeiro objeto:

ModelName.objects.first()

Para obter os últimos objetos:

ModelName.objects.last()

Você pode usar o filtro

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

Isso funciona para mim.

Ravi Kumar
fonte
6

Quando o queryset já estiver esgotado, você pode fazer isso para evitar outra dica de banco de dados -

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

Não use try...except....
Django não joga IndexErrorneste caso.
Ele lança AssertionErrorou ProgrammingError(quando você executa o python com a opção -O)

jifeng.yin
fonte
1
Supondo que seu queryset já esteja ordenado, esta deve ser a "melhor resposta", pois é a única solução que não atinge o banco de dados novamente.
David D.
4

Se estiver usando django 1.6 e superior, é muito mais fácil agora, pois a nova API foi introduzida -

Model.object.earliest()

Ele dará o último () com direção reversa.

ps - Eu sei que é uma questão antiga, estou postando como se fosse pra frente alguém pousar nessa questão, eles ficam conhecendo esse novo recurso e não acabam usando o método antigo.

Mutante
fonte
3
do docs: primeiro () e mais recente () exigem um parâmetro field_name ou 'get_latest_by' no modelo
panchicore
1

Você pode usar Model.objects.last()ou Model.objects.first(). Se não orderingfor definido, o queryset é ordenado com base na chave primária. Se você deseja ordenar o comportamento do queryset, então você pode se referir aos dois últimos pontos.

Se você está pensando em fazer isso, Model.objects.all().last()recuperar o último e Model.objects.all().first()recuperar o primeiro elemento em um queryset ou usar filterssem pensar duas vezes. Então veja algumas advertências abaixo.

A parte importante a observar aqui é que se você não incluiu nenhum orderingem seu modelo, os dados podem estar em qualquer ordem e você terá um último ou primeiro elemento aleatório que não era esperado.

Por exemplo. Digamos que você tenha um modelo chamado Model1com 2 colunas ide item_count10 linhas com id 1 a 10. [Não há ordenação definida]

Se você buscar Model.objects.all (). Last () assim, poderá obter qualquer elemento da lista de 10 elementos. Sim, é aleatório, pois não há ordenação padrão.

Então, o que pode ser feito?

  1. Você pode definir com orderingbase em qualquer campo ou campos em seu modelo. Ele também tem problemas de desempenho, verifique isso também. Ref: aqui
  2. OU você pode usar order_byenquanto busca. Como isso:Model.objects.order_by('item_count').last()
Roshan Dawande
fonte
-5

A maneira mais simples, sem ter que se preocupar com a ordem atual, é converter o QuerySet em uma lista para que você possa usar a indexação negativa normal do Python. Igual a:

list(User.objects.all())[-1]
Josh Ourisman
fonte
2
Isso consultará TODOS os objetos do banco de dados e, em seguida, levará o primeiro
warvariuc
Bom ponto! Obviamente, não pensei nisso. A resposta .reverse () (atualmente selecionada) é o caminho certo a seguir!
Josh Ourisman