Django Query с использованием .order_by () и .latest () - PullRequest
38 голосов
/ 17 сентября 2010

У меня есть модель:

class MyModel(models.Model):
   creation_date = models.DateTimeField(auto_now_add = True, editable=False)

   class Meta:
      get_latest_by = 'creation_date'

У меня был запрос на мой взгляд, который сделал следующее:

instances = MyModel.objects.all().order_by('creation_date')

А потом я захотел instances.latest(), но этоне дать мне правильный экземпляр, на самом деле он дал мне первый экземпляр.Только когда я установил order_by на -creation_date или фактически удалил order_by из запроса, .latest() дал мне правильный экземпляр.Это также происходит, когда я проверяю это вручную, используя python manage.py shell вместо представления.

Итак, что я сделал сейчас, это мета-модель модели, которую я перечислил order_by = ['creation_date'] и не использовал взапрос, и это работает.

Я бы ожидал, что .latest() всегда будет возвращать самый последний экземпляр на основе поля (дата) (время).Может ли кто-нибудь сказать мне, правильно ли, что .latest() ведет себя странно, когда вы используете order_by в запросе?

Ответы [ 3 ]

67 голосов
/ 17 сентября 2010

Я бы ожидал, что .latest () всегда будет возвращать самый последний экземпляр на основе поля (дата) (время).

В документации говорится, что

Если Meta вашей модели указывает get_latest_by, вы можете опустить аргумент field_name для latest().Django будет использовать поле, указанное в get_latest_by по умолчанию.

Все это означает, что при запуске MyModel.objects.latest() вы получите самый последний экземпляр на основе поля даты / времени.И когда я тестировал ваш код, используя примеры данных, он действительно это делал.

А потом я захотел instances.latest (), но он не дал мне правильный экземпляр, фактически он дал мнепервый экземпляр.

Вы неправильно поняли, как работает latest().При вызове MyModel.objects возвращается последний экземпляр в таблице .При вызове queryset , latest вернет первый объект в queryset .Ваш набор запросов состоял из всех экземпляров MyModel, упорядоченных по creation_date в порядке возрастания.Вполне естественно, что latest в этом наборе запросов должен возвращать первую строку набора запросов .Это, кстати, самая старая строка в таблице .

. Чтобы лучше понять это, просмотрите запрос, запущенный для latest.

Случай 1:

from django.db import connection
MyModel.objects.latest()
print connection.queries[-1]['sql']

Это печатает:

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM 
"app_mymodel" ORDER BY "app_mymodel"."creation_date" DESC LIMIT 1

Обратите внимание на порядок по creation_date DESC и предложение LIMIT.Первый - благодаря get_latest_by, а второй - вклад latest.

Теперь, дело 2:

MyModel.objects.order_by('creation_date').latest()
print connection.queries[-1]['sql']

печать

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM 
"app_mymodel" ORDER BY "app_mymodel"."creation_date" ASC LIMIT 1

Обратите внимание, что порядок изменился на creation_date ASC.Это результат явного order_by.LIMIT прикреплен к эр, позже любезно latest.

Рассмотрим также случай 3: вы явно указываете field_name для objects.latest().

MyModel.objects.latest('id')
print connection.queries[-1]['sql']

показывает

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM "app_mymodel"
ORDER BY "app_mymodel"."id" DESC LIMIT 1
7 голосов
/ 14 августа 2011

Полагаю, это известная ошибка в Django , исправленная после выпуска 1.3.

0 голосов
/ 26 октября 2017

Это сработало для меня

latestsetuplist = SetupTemplate.objects.order_by('-creationTime')[:10][::1]
...