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

89

Comment puis-je récupérer le dernier enregistrement dans un certain jeu de requêtes?

Stephen
la source

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).

jujule
la source
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')
Asinox
la source
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()
haky_nash
la source
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.

panchicore
la source
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.

Ravi Kumar
la source
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)

jifeng.yin
la source
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.

Mutant
la source
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()
Roshan Dawande
la source
-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]
Josh Ourisman
la source
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