使用.order_by()和.latest()的Django查询

Hey*_*yl1 39 python django sql-order-by

我有一个模特:

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

   class Meta:
      get_latest_by = 'creation_date'
Run Code Online (Sandbox Code Playgroud)

我在视图中有一个查询,它执行以下操作:

instances = MyModel.objects.all().order_by('creation_date')
Run Code Online (Sandbox Code Playgroud)

然后我想instances.latest(),但它不会给我正确的实例,事实上它给了我第一个实例.只有当我将order_by设置为-creation_date或从查询中实际删除order_by 时才.latest()会给我正确的实例.当我使用python manage.py shell而不是在视图中手动测试时,也会发生这种情况.

所以我现在所做的是在模型的Meta我已经列出order_by = ['creation_date']并且在查询中没有使用它,这是有效的.

我本来希望.latest()总是根据(日期)(时间)字段返回最新的实例.有人能告诉我,.latest()当你order_by在查询中使用时,行为奇怪吗?

Man*_*dan 69

我原以为.latest()总是根据(日期)(时间)字段返回最新的实例.

文件说,

如果您的模型Meta指定get_latest_by,您可以不field_name参数latest().Django将get_latest_by默认使用指定的字段.

所有这些意味着当你开火时,MyModel.objects.latest()你将获得基于日期/时间字段的最新实例.当我使用示例数据测试您的代码时,确实如此.

然后我想要instances.latest(),但它不会给我正确的实例,事实上它给了我第一个实例.

你误解了这种方式latest().当所谓的MyModel.objects它在返回的最新实例.当一个叫做查询集,latest将在返回的第一个对象的查询集.您的查询集MyModelcreation_date按升序排序的所有实例组成.那么latest在这个查询集上返回查询集的第一行是很自然.顺便提一下,这恰好是表格中最老的一行.

获得更好理解的一种方法是查看触发的查询latest.

情况1:

from django.db import connection
MyModel.objects.latest()
print connection.queries[-1]['sql']
Run Code Online (Sandbox Code Playgroud)

这打印:

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM 
"app_mymodel" ORDER BY "app_mymodel"."creation_date" DESC LIMIT 1
Run Code Online (Sandbox Code Playgroud)

请注意排序依据creation_date DESCLIMIT子句.前者是感谢get_latest_by而后者是贡献latest.

现在,案例2:

MyModel.objects.order_by('creation_date').latest()
print connection.queries[-1]['sql']
Run Code Online (Sandbox Code Playgroud)

版画

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM 
"app_mymodel" ORDER BY "app_mymodel"."creation_date" ASC LIMIT 1
Run Code Online (Sandbox Code Playgroud)

请注意,订购已更改为creation_date ASC.这是明确的结果order_by.这LIMIT是呃,后来礼貌latest.

让我们看一下案例3:您明确指定field_namefor的位置objects.latest().

MyModel.objects.latest('id')
print connection.queries[-1]['sql']
Run Code Online (Sandbox Code Playgroud)

节目

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM "app_mymodel"
ORDER BY "app_mymodel"."id" DESC LIMIT 1
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您的精彩解释!你已经让我非常清楚 .latest() 是如何工作的以及我做错了什么。尤其是 SQL 技巧很有帮助。这在将来肯定会派上用场。 (2认同)

小智 7

我想这是Django中一个已知的错误,在1.3发布后修复了.