2010-09-17 99 views
37

我有一个模型:Django的查询使用.order_by()和.latest()

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

回答

64

我会期待.latest()总是返回基于(日期)(时间)字段的最新实例。

documentation

如果模型的Meta指定get_latest_by,您可以在field_name参数离开关闭以latest()。 Django默认使用get_latest_by中指定的字段。

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

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

您误解了latest()的工作方式。当在上调用MyModel.objects时,它返回 中的最新实例。当在查询集叫,latest将在的查询集返回的第一个对象。您的查询集包括由creation_date升序排列有序的MyModel所有实例。那么这个查询集上的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_nameobjects.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 
+1

非常感谢您对您出色的解释!你已经很清楚地告诉我.latest()的工作原理以及我做错了什么。特别是SQL技巧是有帮助的。这在将来肯定会派上用场。 – Heyl1 2010-09-20 07:26:46

+1

如果我只想只有1个特定的最近插入的列值,该怎么办?假设:select“app_mymodel”。“id”FROM “app_mymodel”ORDER BY“app_mymodel”。“creation_date”ASC LIMIT 1,什么是等效的Python代码? – 2015-10-19 07:29:15

7

我想这是一个已知的bug in Django 1.3发布之后是固定的。

0

这为我工作

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