使用 .order_by() 和 .latest() 进行 Django 查询

发布于 2024-09-24 01:40:04 字数 738 浏览 0 评论 0原文

我有一个模型:

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() 始终返回基于(日期)(时间)字段的最新实例。谁能告诉我当您在查询中使用 order_by.latest() 表现奇怪是否正确?

I have a model:

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

   class Meta:
      get_latest_by = 'creation_date'

I had a query in my view that did the following:

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

And then later I wanted instances.latest(), but it would not give me the correct instance, in fact it gave me the first instance. Only when I set order_by to -creation_date or actually removed the order_by from the query did .latest() give me the correct instance. This also happens when I test this manually using python manage.py shell instead of in the view.

So what I've done now is in the Model's Meta I've listed order_by = ['creation_date'] and not used that in the query, and that works.

I would have expected .latest() to always return the most recent instance based on a (date)(time) field. Could anyone tell me whether it's correct that .latest() behaves strangely when you use order_by in the query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

扶醉桌前 2024-10-01 01:40:04

我希望 .latest() 始终返回基于(日期)(时间)字段的最新实例。

文档

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

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

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

您误解了 latest() 的工作方式。当调用 MyModel.objects 时,它返回
中的最新实例。当调用查询集时,latest 将返回查询集中中的第一个对象。您的查询集包含按 creation_date 升序排列的 MyModel 的所有实例。很自然,此查询集上的最新应该返回查询集的第一。顺便说一句,这恰好是表中最旧的行。

更好地理解的一种方法是查看针对 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 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

I would have expected .latest() to always return the most recent instance based on a (date)(time) field.

The documentation says that

If your model's Meta specifies get_latest_by, you can leave off the field_name argument to latest(). Django will use the field specified in get_latest_by by default.

All this means is that when you fire MyModel.objects.latest() you will get the latest instance based on the date/time field. And when I tested your code using sample data, it indeed did.

And then later I wanted instances.latest(), but it would not give me the correct instance, in fact it gave me the first instance.

You have misunderstood the way latest() works. When called on MyModel.objects it returns
the latest instance in the table. When called on a queryset, latest will return the first object in the queryset. Your queryset consisted of all instances of MyModel ordered by creation_date in ascending order. It is only natural then that latest on this queryset should return the first row of the queryset. This incidentally happens to be the oldest row in the table.

One way to get a better understanding is to view the query fired for latest.

Case 1:

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

This prints:

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

Note the ordering by creation_date DESC and the LIMIT clause. The former is thanks to get_latest_by whereas the latter is the contribution of latest.

Now, case 2:

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

prints

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

Note that the ordering has changed to creation_date ASC. This is the result of the explicit order_by. The LIMIT is tacked on er, later courtesy latest.

Let us also see Case 3: where you explicitly specify the field_name for objects.latest().

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

shows

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM "app_mymodel"
ORDER BY "app_mymodel"."id" DESC LIMIT 1
£噩梦荏苒 2024-10-01 01:40:04

我猜这是一个已知的 Django 中的 bug 在 1.3 版本后已修复被释放了。

I guess this is a known bug in Django that was fixed after 1.3 was released.

以往的大感动 2024-10-01 01:40:04

这对我有用

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

This worked for me

latestsetuplist = SetupTemplate.objects.order_by('-creationTime')[:10][::1]
执笔绘流年 2024-10-01 01:40:04

如果我们有 id 或日期的值

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,它也会选择该值的下一个或上一个值

if we have the value of id or 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

it worked for me, even if an id is missing it picks next or previous value to that

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文