我有一个QuerySet,我们称之为qs
,它由一些与此问题无关的属性排序。然后我有一个对象,我们称之为obj
。现在,我想知道obj
中的qs
索引,{em>有效。我知道我可以使用Python中的.index()
或者可能循环通过qs
将每个对象与obj
进行比较,但是这样做的最佳方法是什么?我正在寻找高性能,这是我唯一的标准。
在Windows上使用Python 2.6.2和Django 1.0.2。
答案 0 :(得分:58)
紧凑,可能效率最高:
for index, item in enumerate(your_queryset):
...
答案 1 :(得分:30)
如果您只是想知道对象在哪里(例如在确定等级时),您可以通过在您之前计算对象来快速完成:
index = MyModel.objects.filter(sortField__lt = myObject.sortField).count()
答案 2 :(得分:16)
Django中的QuerySet实际上是生成器,而不是列表(有关详细信息,请参阅Django documentation on QuerySets)。
因此,没有获取元素索引的快捷方式,我认为普通迭代是最好的方法。
对于初学者,我会以最简单的方式实现您的要求(如迭代);如果你确实遇到了性能问题,那么我会使用一些不同的方法,比如用少量字段构建一个查询集,或者其他什么。
在任何情况下,当你确定知道你需要它们时,我们的想法就是尽可能晚地留下这些技巧
更新:您可能希望直接使用一些SQL语句来获取rownumber(有些谎言。但是,Django的ORM本身不支持这种情况,您必须使用原始SQL查询(请参阅{{3}) })。我认为这可能是最好的选择,但同样 - 只有你真的看到了真正的性能问题。
答案 3 :(得分:12)
假设为了说明的目的,您的模型是标准的主键id
,那么评估
list(qs.values_list('id', flat=True)).index(obj.id)
会在obj
中找到qs
的索引。虽然list
的使用会评估查询集,但它不会评估原始查询集,而是评估派生的查询集。此评估运行SQL查询以仅获取id字段,而不是浪费时间获取其他字段。
答案 4 :(得分:2)
您可以使用queryset.extra(…)
和一些原始SQL执行此操作:
queryset = queryset.order_by("id")
record500 = queryset[500]
numbered_qs = queryset.extra(select={
'queryset_row_number': 'ROW_NUMBER() OVER (ORDER BY "id")'
})
from django.db import connection
cursor = connection.cursor()
cursor.execute(
"WITH OrderedQueryset AS (" + str(numbered_qs.query) + ") "
"SELECT queryset_row_number FROM OrderedQueryset WHERE id = %s",
[record500.id]
)
index = cursor.fetchall()[0][0]
index == 501 # because row_number() is 1 indexed not 0 indexed
答案 5 :(得分:2)
可以通过简单的pythonic方法查询查询集中元素的索引:
(*qs,).index(instance)
此答案会将查询集解压缩为一个列表,然后使用内置的Python索引函数确定其位置。