我有一个 QuerySet,我们称之为它qs
,它是由一些与这个问题无关的属性排序的。然后我有一个对象,我们称之为obj
。现在,我想尽可能有效obj
地知道in 中的索引。我知道我可以从 Python 中使用,或者可能通过将每个对象与 进行比较来循环,但是最好的方法是什么?我正在寻找高性能,这是我唯一的标准。qs
.index()
qs
obj
在 Windows 上使用 Python 2.6.2 和 Django 1.0.2。
我有一个 QuerySet,我们称之为它qs
,它是由一些与这个问题无关的属性排序的。然后我有一个对象,我们称之为obj
。现在,我想尽可能有效obj
地知道in 中的索引。我知道我可以从 Python 中使用,或者可能通过将每个对象与 进行比较来循环,但是最好的方法是什么?我正在寻找高性能,这是我唯一的标准。qs
.index()
qs
obj
在 Windows 上使用 Python 2.6.2 和 Django 1.0.2。
如果您已经在遍历查询集并且只想知道您当前所在元素的索引,那么紧凑且可能最有效的解决方案是:
for index, item in enumerate(your_queryset):
...
但是,如果您有一个查询集和一个通过某种不相关方式获得的对象,并且想要了解该对象在查询集中的位置(如果它甚至存在),则不要使用它。
如果您只想知道您的对象在所有其他对象中的位置(例如,在确定排名时),您可以通过计算您面前的对象来快速完成:
index = MyModel.objects.filter(sortField__lt = myObject.sortField).count()
Django 中的 QuerySets 实际上是生成器,而不是列表(有关更多详细信息,请参阅Django 文档中的 QuerySets)。
因此,获取元素的索引没有捷径,我认为简单的迭代是最好的方法。
首先,我会以最简单的方式实现您的要求(如迭代);如果你真的有性能问题,那么我会使用一些不同的方法,比如构建一个带有少量字段的查询集,或者其他什么。
无论如何,我们的想法是尽可能晚地离开这些技巧,当你确定你需要它们时。
更新:您可能想直接使用一些 SQL 语句来获取行号(有些谎言。但是,Django 的 ORM 本身不支持这一点,您必须使用原始 SQL 查询(参见文档)。我认为这可能是最好的选择,但同样 - 只有当您真的看到真正的性能问题时。
假设您的模型是带有主键的标准模型id
,然后评估
list(qs.values_list('id', flat=True)).index(obj.id)
将找到obj
in的索引qs
。虽然使用list
评估查询集,但它评估的不是原始查询集,而是派生查询集。此评估运行 SQL 查询以仅获取 id 字段,而不是浪费时间获取其他字段。
可以使用一种简单的 Python 方式来查询查询集中元素的索引:
(*qs,).index(instance)
这个答案会将查询集解包到一个列表中,然后使用内置的 Python 索引函数来确定它的位置。
您可以使用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