【问题标题】:Django Query using .order_by() and .latest()使用 .order_by() 和 .latest() 的 Django 查询
【发布时间】:2010-09-17 16:02:06
【问题描述】:

我有一个模型:

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() 总是根据(日期)(时间)字段返回最新的实例。谁能告诉我当您在查询中使用order_by.latest() 的行为异常是否正确?

【问题讨论】:

  • 只有当我将 order_by 设置为 -creation_date 或实际从查询中删除 order_by 时, .latest() 才给我正确的实例......你能解释一下这句话是什么意思吗?我不明白...

标签: python django sql-order-by


【解决方案1】:

我本来希望 .latest() 总是根据(日期)(时间)字段返回最新的实例。

documentation 这么说

如果您的模型的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 应该返回查询集的第一行行。这恰好是 table 中最旧的行。

更好地理解的一种方法是查看为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 DESCLIMIT 子句的排序。前者感谢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:您为 objects.latest() 明确指定 field_name

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

【讨论】:

  • 非常感谢您的精彩解释!您已经让我非常清楚 .latest() 的工作原理以及我做错了什么。特别是 SQL 技巧很有帮助。这在未来肯定会派上用场。
  • 如果我只想有 1 个特定的最近插入的列值怎么办?比如说:select "app_mymodel"."id" FROM "app_mymodel" ORDER BY "app_mymodel"."creation_date" ASC LIMIT 1,对应的python代码是什么?
  • 现在你应该更新你的答案,因为MyModel.objects.latest()MyModel.objects.all().latest(') 返回相同的结果..
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    这对我有用

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

    【讨论】:

      【解决方案4】:

      如果我们有 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 它也会选择下一个或上一个值

      【讨论】:

        猜你喜欢
        • 2020-02-27
        • 2016-01-16
        • 1970-01-01
        • 2012-04-07
        • 2015-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-30
        相关资源
        最近更新 更多