48

我有一个 QuerySet,我们称之为它qs,它是由一些与这个问题无关的属性排序的。然后我有一个对象,我们称之为obj。现在,我想尽可能有效obj地知道in 中的索引。我知道我可以从 Python 中使用,或者可能通过将每个对象与 进行比较来循环,但是最好的方法是什么?我正在寻找高性能,这是我唯一的标准。qs.index()qsobj

在 Windows 上使用 Python 2.6.2 和 Django 1.0.2。

4

6 回答 6

65

如果您已经在遍历查询集并且只想知道您当前所在元素的索引,那么紧凑且可能最有效的解决方案是:

for index, item in enumerate(your_queryset):
    ...

但是,如果您有一个查询集和一个通过某种不相关方式获得的对象,并且想要了解该对象在查询集中的位置(如果它甚至存在),则不要使用它。

于 2009-06-25T07:50:35.197 回答
46

如果您只想知道您的对象在所有其他对象中的位置(例如,在确定排名时),您可以通过计算您面前的对象来快速完成:

    index = MyModel.objects.filter(sortField__lt = myObject.sortField).count()
于 2013-02-08T12:13:05.180 回答
24

Django 中的 QuerySets 实际上是生成器,而不是列表(有关更多详细信息,请参阅Django 文档中的 QuerySets)。
因此,获取元素的索引没有捷径,我认为简单的迭代是最好的方法。

首先,我会以最简单的方式实现您的要求(如迭代);如果你真的有性能问题,那么我会使用一些不同的方法,比如构建一个带有少量字段的查询集,或者其他什么。
无论如何,我们的想法是尽可能晚地离开这些技巧,当你确定你需要它们时。
更新:您可能想直接使用一些 SQL 语句来获取行号(有些谎言。但是,Django 的 ORM 本身不支持这一点,您必须使用原始 SQL 查询(参见文档)。我认为这可能是最好的选择,但同样 - 只有当您真的看到真正的性能问题时。

于 2009-06-25T07:43:46.130 回答
23

假设您的模型是带有主键的标准模型id,然后评估

list(qs.values_list('id', flat=True)).index(obj.id)

将找到objin的索引qs。虽然使用list评估查询集,但它评估的不是原始查询集,而是派生查询集。此评估运行 SQL 查询以仅获取 id 字段,而不是浪费时间获取其他字段。

于 2009-06-25T15:22:17.907 回答
6

可以使用一种简单的 Python 方式来查询查询集中元素的索引:

(*qs,).index(instance)

这个答案会将查询集解包到一个列表中,然后使用内置的 Python 索引函数来确定它的位置。

于 2019-03-06T17:03:40.957 回答
4

您可以使用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
于 2014-01-30T20:17:59.167 回答