获取查询集中元素的索引

时间:2009-06-25 07:31:25

标签: python django indexing django-queryset

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

在Windows上使用Python 2.6.2和Django 1.0.2。

6 个答案:

答案 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索引函数确定其位置。