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

时间:2010-09-17 16:02:07

标签: 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'

我的观点中有一个查询执行了以下操作:

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

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

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

我希望.latest()始终根据(日期)(时间)字段返回最新的实例。当你在查询中使用.latest()时,有人能告诉我order_by是否表现得很奇怪?

4 个答案:

答案 0 :(得分:67)

  

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

documentation

  

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

所有这些意味着当您解雇MyModel.objects.latest()时,您将根据日期/时间字段获取最新实例。当我使用示例数据测试您的代码时,确实如此。

  

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

你误解了latest()的工作方式。在 MyModel.objects 上调用时,它会返回 中的最新实例。在 queryset 上调用时,latest将返回查询集中的第一个对象。您的查询集由MyModel按{1}}按升序排序的所有实例组成。很自然,此查询集上的creation_date应该返回查询集第一行。这恰好是中最旧的行。

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

案例1:

latest

打印:

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的贡献。

现在,案例2:

latest

打印

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

让我们看一下案例3:您明确指定latest的{​​{1}}。

field_name

显示

objects.latest()

答案 1 :(得分:7)

我想这是一个已知的bug in Django,在1.3发布后修复了。

答案 2 :(得分:0)

这对我有用

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

答案 3 :(得分:0)

如果我们有 id 或 date 的值

post_id = BlogPost.objects.get(id=id)
try:
   previous_post = BlogPost.objects.all().order_by('id')[post_id.id-2:post_id.id-1]
except:   
   previous_post = None
try:
   next_post = BlogPost.objects.all().order_by('id')[post_id.id:post_id.id+1]
except:
  next_post = None

它对我有用,即使缺少 id 它也会选择下一个或上一个值