Obtenir le dernier enregistrement d'un ensemble de requêtes


Réponses:


81

EDIT: Vous devez maintenant utiliser Entry.objects.latest('pub_date')


Vous pouvez simplement faire quelque chose comme ça, en utilisant reverse():

queryset.reverse()[0]

Attention également à cet avertissement de la documentation Django:

... notez qu'il reverse()ne doit généralement être appelé que sur un QuerySet qui a un ordre défini (par exemple, lors d'une requête sur un modèle qui définit un ordre par défaut, ou lors de l'utilisation order_by()). Si aucun ordre de ce type n'est défini pour un ordre donné QuerySet, l'appel reverse()sur celui-ci n'a aucun effet réel (l'ordre n'était pas défini avant l'appel reverse(), et restera indéfini par la suite).


2
comme dit dans django docs,: "notez que reverse () ne doit généralement être appelé que sur un QuerySet qui a un ordre défini (par exemple, lors d'une requête sur un modèle qui définit un ordre par défaut, ou lors de l'utilisation de order_by ()). Si non un tel ordre est défini pour un QuerySet donné, appeler reverse () sur celui-ci n'a aucun effet réel (l'ordre était indéfini avant d'appeler reverse (), et restera indéfini par la suite). "
jujule

6
2017 et les réponses acceptées sont maintenant obsolètes. Comme indiqué ci-dessous, vous devez utiliser queryset.last ().
wobbily_col

134

Django Doc :

latest(field_name=None) renvoie le dernier objet de la table, par date, en utilisant le nom de champ fourni comme champ de date.

Cet exemple renvoie la dernière entrée de la table, en fonction du pub_datechamp:

Entry.objects.latest('pub_date')

5
C'est la bonne façon de le faire. De plus, "Si la méta de votre modèle spécifie get_latest_by, vous pouvez laisser l'argument field_name à latest ()" selon la documentation.
Fredrik Möllerstrand

50

La façon la plus simple de le faire est:

books.objects.all().last()

Vous utilisez également ceci pour obtenir la première entrée comme ceci:

books.objects.all().first()

16
books.objects.last() et books.objects.first()devrait faire l'affaire.
chandan

Cela devrait être la réponse acceptée avec XYZ.objects.first()et XYZ.objects.last()
slajma

Je pense que la voie d'Arnaud P est la plus appropriée. Si ce n'est pas faux, tous les éléments de la base de données seront décompressés où le dernier extrait le dernier à l'aide de la requête de base de données.
Larcho

33

Django> = 1,6

Ajout des méthodes QuerySet first () et last () qui sont des méthodes pratiques renvoyant le premier ou le dernier objet correspondant aux filtres. Renvoie None s'il n'y a aucun objet correspondant.


32

Pour obtenir le premier objet:

ModelName.objects.first()

Pour obtenir les derniers objets:

ModelName.objects.last()

Vous pouvez utiliser le filtre

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

Cela fonctionne pour moi.


6

Lorsque le jeu de requêtes est déjà épuisé, vous pouvez le faire pour éviter un autre indice de base de données -

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

N'utilisez pas try...except....
Django ne lance pas IndexErrordans ce cas.
Il lance AssertionErrorou ProgrammingError(lorsque vous exécutez python avec l'option -O)


1
En supposant que votre jeu de requêtes est déjà ordonné, cela devrait être la "réponse principale", car c'est la seule solution qui n'atteint plus la base de données.
David D.

4

Si vous utilisez django 1.6 et plus, c'est beaucoup plus facile maintenant que la nouvelle API a été introduite -

Model.object.earliest()

Il donnera la dernière () avec la direction inverse.

ps - Je connais son ancienne question, je poste comme si à l'avenir quelqu'un atterrit sur cette question, ils apprennent à connaître cette nouvelle fonctionnalité et ne finissent pas par utiliser l'ancienne méthode.


3
from docs: earliest () et latest () nécessitent un paramètre field_name ou 'get_latest_by' dans le modèle
panchicore

1

Vous pouvez utiliser Model.objects.last()ou Model.objects.first(). Si aucun orderingn'est défini, l'ensemble de requêtes est trié en fonction de la clé primaire. Si vous voulez ordonner le jeu de requêtes de comportement, vous pouvez vous référer aux deux derniers points.

Si vous envisagez de faire cela, Model.objects.all().last()pour récupérer le dernier et Model.objects.all().first()pour récupérer le premier élément d'un jeu de requêtes ou en utilisantfilters sans pensée. Ensuite, voyez quelques mises en garde ci-dessous.

La partie importante à noter ici est que si vous n'en avez pas inclus orderingdans votre modèle, les données peuvent être dans n'importe quel ordre et vous aurez un dernier ou un premier élément aléatoire qui n'était pas attendu.

Par exemple. Disons que vous avez un modèle nommé Model1qui a 2 colonnes idetitem_count 10 lignes ayant les id 1 à 10. [Il n'y a pas de classement défini]

Si vous récupérez Model.objects.all (). Last () comme ceci, vous pouvez obtenir n'importe quel élément de la liste des 10 éléments. Oui, c'est aléatoire car il n'y a pas de commande par défaut.

Alors qu'est ce qui peut être fait?

  1. Vous pouvez définir en orderingfonction de n'importe quel champ ou champs de votre modèle. Il a également des problèmes de performances, veuillez vérifier cela également. Réf: Ici
  2. OU vous pouvez utiliser order_bylors de la récupération. Comme ça:Model.objects.order_by('item_count').last()

-5

Le moyen le plus simple, sans avoir à vous soucier de l'ordre actuel, consiste à convertir le QuerySet en liste afin que vous puissiez utiliser l'indexation négative normale de Python. Ainsi:

list(User.objects.all())[-1]

2
Cela interrogera TOUS les objets de la base de données, puis prendra le premier
warvariuc

Bon point! Évidemment, je n'ai pas pensé à ça. La réponse .reverse () (actuellement sélectionnée) est la bonne voie à suivre!
Josh Ourisman
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.