关于django:django-限制查询结果

Django - limiting query results

我想获取模型的最后10个实例,并具有以下代码:

1
 Model.objects.all().order_by('-id')[:10]

首先收集所有实例,然后只取最后10个实例,这是真的吗?还有更有效的方法吗?


Django查询集是懒惰的。这意味着只有当您特别要求结果时,查询才会命中数据库。

因此,在打印或实际使用查询结果之前,您可以在没有数据库访问的情况下进行进一步筛选。

正如您在下面看到的,您的代码只执行一个SQL查询来获取最后10个项目。

1
2
3
4
5
6
7
In [19]: import logging                                
In [20]: l = logging.getLogger('django.db.backends')    
In [21]: l.setLevel(logging.DEBUG)                      
In [22]: l.addHandler(logging.StreamHandler())      
In [23]: User.objects.all().order_by('-id')[:10]          
(0.000) SELECT"auth_user"."id","auth_user"."username","auth_user"."first_name","auth_user"."last_name","auth_user"."email","auth_user"."password","auth_user"."is_staff","auth_user"."is_active","auth_user"."is_superuser","auth_user"."last_login","auth_user"."date_joined" FROM"auth_user" ORDER BY"auth_user"."id" DESC LIMIT 10; args=()
Out[23]: [<User: hamdi>]


实际上,我认为LIMIT 10将被发布到数据库中,因此切片不会在python中发生,而是在数据库中发生。

有关详细信息,请参阅限制查询集。


似乎问题中的解决方案不再适用于Django 1.7,并引发错误:"获取切片后无法对查询重新排序"

根据文档https://docs.djangoproject.com/en/dev/topics/db/queries/limiting queryset强制使用python slice语法的"step"参数来评估查询。它是这样工作的:

1
Model.objects.all().order_by('-id')[:10:1]

不过,我想知道这个限制是在SQL还是Python中执行的,它将返回整个结果数组切片。在应用程序内存中检索巨大的列表是没有好处的。


对。如果要获取对象的有限子集,可以使用以下代码:

例子:

1
obj=emp.objects.all()[0:10]

开头0是可选的,因此

1
obj=emp.objects.all()[:10]

上面的代码返回前10个实例。


作为对其他有用答案的补充和观察,值得注意的是,实际执行EDOCX1[1]作为切片将返回列表的前10个元素,而不是最后10个元素…

为了得到最后10个,你应该改为使用[-10:](见这里)。这将帮助您避免使用order_by('-id')-来反转元素。


事实并非如此。Django不只获取所需的结果。Django将加载完整的数据库表(这是一个愚蠢的[id操作),并只返回最后10条记录。

我已经通过在mysql服务器上运行show full processlist确认了这一点,并且查询没有limit子句。

如果要开发一个需要高可伸缩性的大型应用程序,Django不是一个好的选择。