J'ai un modèle:
class MyModel(models.Model):
creation_date = models.DateTimeField(auto_now_add = True, editable=False)
class Meta:
get_latest_by = 'creation_date'
J'ai eu une question à mon avis qui a fait ce qui suit:
instances = MyModel.objects.all().order_by('creation_date')
Et puis plus tard, je voulais instances.latest()
, mais cela ne me donnait pas le bon exemple, mais en fait le premier exemple. Ce n'est que lorsque j'ai défini order_by sur -creation_date
ou que j'ai effectivement supprimé order_by de la requête, .latest()
m'a donné l'instance correcte. Cela se produit également lorsque je teste cela manuellement à l’aide de python manage.py Shell plutôt que dans la vue.
Donc, ce que j'ai fait maintenant est dans la méta du modèle, j'ai répertorié order_by = ['creation_date']
et je ne l'ai pas utilisé dans la requête, et cela fonctionne.
Je me serais attendu à ce que .latest()
renvoie toujours l'instance la plus récente en fonction d'un champ (date) (heure). Quelqu'un peut-il me dire s'il est correct que .latest()
se comporte étrangement lorsque vous utilisez order_by
dans la requête?
J'aurais pensé que .latest () renverrait toujours l'instance la plus récente en fonction d'un champ (date) (heure).
La documentation dit que
Si la variable
Meta
de votre modèle spécifieget_latest_by
, vous pouvez laisser l'argumentfield_name
àlatest()
. Django utilisera le champ spécifié dansget_latest_by
par défaut.
Cela signifie simplement que lorsque vous déclenchez MyModel.objects.latest()
, vous obtiendrez la dernière instance en fonction du champ date/heure. Et lorsque j'ai testé votre code en utilisant des exemples de données, c'est effectivement le cas.
Et puis plus tard, je voulais instances.latest (), mais cela ne me donnait pas l'instance correcte, mais plutôt la première instance.
Vous avez mal compris le fonctionnement de latest()
. Lorsqu'il est appelé sur MyModel.objects, il retourne La dernière instance de table. Lorsqu'il est appelé sur un queryset, latest
renvoie le premier objet dans le queryset. Votre ensemble de requêtes était composé de toutes les instances de MyModel
ordonnées par creation_date
par ordre croissant. Il est donc naturel que latest
de ce queryset retourne la première ligne du queryset. Il se trouve d'ailleurs que cette ligne est la plus ancienne de la table.
Une façon de mieux comprendre consiste à afficher la requête déclenchée pour latest
.
Cas 1:
from Django.db import connection
MyModel.objects.latest()
print connection.queries[-1]['sql']
Cela imprime:
SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM
"app_mymodel" ORDER BY "app_mymodel"."creation_date" DESC LIMIT 1
Notez le classement par creation_date DESC
et la clause LIMIT
. Le premier est grâce à get_latest_by
alors que le dernier est la contribution de latest
.
Maintenant, cas 2:
MyModel.objects.order_by('creation_date').latest()
print connection.queries[-1]['sql']
empreintes
SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM
"app_mymodel" ORDER BY "app_mymodel"."creation_date" ASC LIMIT 1
Notez que la commande a été modifiée en creation_date ASC
. Ceci est le résultat du order_by
explicite. La LIMIT
est ajoutée, plus tard, avec la permission de latest
.
Voyons également le cas 3: où vous spécifiez explicitement le field_name
pour objects.latest()
.
MyModel.objects.latest('id')
print connection.queries[-1]['sql']
spectacles
SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM "app_mymodel"
ORDER BY "app_mymodel"."id" DESC LIMIT 1
Je suppose que ceci est un bug connu dans Django qui a été corrigé après la publication de la version 1.3.
Cela a fonctionné pour moi
latestsetuplist = SetupTemplate.objects.order_by('-creationTime')[:10][::1]