在 Django QuerySet 中指定限制和偏移量不起作用

Posted

技术标签:

【中文标题】在 Django QuerySet 中指定限制和偏移量不起作用【英文标题】:Specifying limit and offset in Django QuerySet wont work 【发布时间】:2014-07-25 08:09:53 【问题描述】:

我使用的是 Django 1.6.5 并打开了 mysql 的通用查询日志,所以我可以看到 sql 命中 MySQL。 而且我注意到在 Django 的 QuerySet 中指定更大的限制不起作用:

>>> from blog.models import Author  
>>> len(Author.objects.filter(pk__gt=0)[0:999])
>>> len(Author.objects.all()[0:999])

MySQL 的一般日志显示两个查询都有LIMIT 21

但是小于 21 的限制会起作用,例如len(Author.objects.all()[0:10]) 将使用 LIMIT 10 创建一个 sql。

这是为什么呢?有什么需要配置的吗?

【问题讨论】:

那只表示数据库中有21个条目,注意slice不会报错。 【参考方案1】:

Django 使用 Python 的数组切片语法实现 OFFSET。如果要偏移前 10 个元素,然后显示接下来的 5 个元素,请使用它

MyModel.objects.all()[OFFSET:OFFSET+LIMIT]

例如,如果您想在偏移量 10 后检查 5 个作者,那么您的代码将如下所示:

Author.objects.all()[10:15]

您可以阅读更多关于它的信息here in the official Django doc

我也围绕这个概念写了一篇博客,you can here more here

【讨论】:

【参考方案2】:

LIMITOFFSET 在 Django 中的工作方式与我们期望的不同。

例如。

如果我们必须从第 10 行开始读取接下来的 10 行,并且如果我们指定:

Author.objects.all()[10:10]

它将返回空记录列表。为了获取接下来的 10 行,我们必须将偏移量添加到限制中。

Author.objects.all()[10:10+10]

它会返回从第10行开始的下10行的记录列表。

【讨论】:

【参考方案3】:

我确实可以工作,但 django 使用了迭代器。它不会一次加载所有对象。

【讨论】:

【参考方案4】:

对于我使用和为我工作的偏移量和限制:)

MyModel.objects.all()[offset:limit]

例如:-

Post.objects.filter(Post_type=typeId)[1:1]

【讨论】:

我认为切片应该是[offset: offset + limit] 但事实并非如此@neuront 它的 [offset:limit] 把它想象成 [FROM:TO] 当我使用带有偏移量和限制的过滤器时,我得到这个错误 '>=' not supported between 'str' and 'int'【参考方案5】:

当您从 shell 进行查询时会发生这种情况 - 添加了 LIMIT 子句以阻止您的终端在调试时填满数千条记录:

您正在打印(或至少尝试打印) 查询集。为了避免人们不小心尝试检索和打印 百万个结果,我们(好吧,我)将其更改为仅检索和打印 如果有更多结果,则打印前 20 个结果并打印“remainder truncated”。 这是通过将查询限制为 21 个结果来实现的(如果有 21 个 结果有 20 多个,因此我们打印“截断”消息)。 这只发生在 repr() 中 - 即它仅用于诊断 印刷。没有普通用户代码会自动包含此限制,因此 您很高兴地创建了一个迭代超过一百万个结果的查询集。

(Source)

【讨论】:

我从来不知道。如果可以的话,我会投票 10 次!

以上是关于在 Django QuerySet 中指定限制和偏移量不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 邮件中指定名称?

django 在 SQL Server 中指定列排列

在运行时在 Django 中指定关系动词?

如何在 django 中指定索引类型? (btree 与哈希等)

在 settings.py 中指定 Django 测试数据库名称

如何在 Django 的设置文件中指定多个“init_command”