在Django中,如果我想以DESCENDING顺序获取模型的最新10个实例,我可以这样做:
MyModel.objects.order_by(‘-the_field_I_want_to_order_by’)[:10]
但是如何以ASCENDING顺序获取最新的10个实例?我知道从数据库中提取它们后我可以在内存中对它们进行重新排序:
reversed(MyModel.objects.order_by(‘-the_field_I_want_to_order_by’)[:10])
但我很好奇是否有办法只使用查询集。
使用2个查询,我想我可以做类似的事情:
count = MyModel.objects.count()
MyModel.objects.order_by(‘the_field_I_want_to_order_by’)[count-10:]
但是如果可能的话,用一个查询来获取它会很好。
修改
只是为了澄清,我并不是说上述技术太慢,或者说不可接受,或者需要避免。这个问题的目的只是通过QuerySet API找出什么是/不可用的,以便按升序获得最新的X结果。
答案 0 :(得分:2)
您可以像往常一样使用切片表示法:
MyModel.objects.order_by('-the_field_I_want_to_order_by')[:10][::-1]
原因是最后一个切片没有被转换为SQL - 它强制QuerySet进行评估并将其转换为列表。 (这也意味着它不需要额外的查询。)
>>> type(MyModel.objects.order_by('-the_field_I_want_to_order_by')[:10])
<class 'django.db.models.query.QuerySet'>
>>> type(MyModel.objects.order_by('-the_field_I_want_to_order_by')[:10][::-1])
<type 'list'>
在Python 2.7上测试Django 1.5。
您也可以使用第二种方法,只使用一种类似策略的查询(强制评估列表):
list(MyModel.objects.order_by('the_field_I_want_to_order_by'))[-10:]
这种方式效率较低,因为它强制创建与MyModel.objects.all()
大小相同的列表。
答案 1 :(得分:1)
感谢大家的投入。有几个人将答案作为评论发布,但不是答案......所以这里的答案形式是为了以后更容易看到:
似乎答案是 NO,您无法使用单个QuerySet以升序获得最新的X结果,因为Django不支持从末尾开始切片。结果需要在内存中重新排序:
reversed(MyModel.objects.order_by(‘-the_field_I_want_to_order_by’)[:10])
# or, reorder in memory using the technique suggested by Two-Bit Alchemist:
MyModel.objects.order_by('-the_field_I_want_to_order_by')[:10][::-1]
或者你需要两次点击数据库(或者以某种方式神奇地知道你的查询集中有多少项):
qs = MyModel.objects.order_by(‘the_field_I_want_to_order_by’)
count = qs.count()
MyModel.objects.order_by(‘the_field_I_want_to_order_by’)[count-10:]
除非您从数据库中检索TON项目,否则前一种技术可能不仅更简洁,而且效率更高。