Подтвердить что ты не робот

Получить индекс элемента в наборе запросов

У меня есть QuerySet, позвоните ему qs, который упорядочен некоторым атрибутом, который не имеет отношения к этой проблеме. Тогда у меня есть объект, пусть назовите его obj. Теперь я хотел бы узнать, какой индекс obj имеет в qs, насколько это возможно. Я знаю, что я мог бы использовать .index() из Python или, возможно, цикл через qs, сравнивая каждый объект с obj, но что это лучший способ сделать это? Я ищу высокую производительность и мои единственные критерии.

Использование Python 2.6.2 с Django 1.0.2 в Windows.

4b9b3361

Ответ 1

QuerySets в Django на самом деле являются генераторами, а не списками (для получения дополнительной информации см. документация Django на QuerySet).
Таким образом, нет ярлыка для получения индекса элемента, и я думаю, что простая итерация - лучший способ сделать это.

Для стартера я бы выполнил ваше требование самым простым способом (например, итерацией); если у вас действительно проблемы с производительностью, тогда я бы использовал другой подход, например, создание запроса с меньшим количеством полей или что-то еще.
В любом случае, идея состоит в том, чтобы оставить такие трюки как можно дольше, когда вы определенно знаете, что они вам нужны.
Обновление: Возможно, вы захотите напрямую использовать некоторый оператор SQL для получения rownumber (что-то ложь. Однако Django ORM не поддерживает это изначально, и вам нужно использовать необработанный SQL-запрос (см. документация). Я думаю, что это может быть лучшим вариантом, но опять же - только если вы действительно видите реальную проблему с производительностью.

Ответ 2

Компактный и, вероятно, самый эффективный:

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

Ответ 3

Если вы просто хотите знать, где вы находитесь, среди всех остальных (например, при определении ранга), вы можете сделать это быстро, посчитав объекты перед вами:

    index = MyModel.objects.filter(sortField__lt = myObject.sortField).count()

Ответ 4

Предполагая с целью иллюстрации, что ваши модели являются стандартными с первичным ключом id, затем оценивая

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

найдет индекс obj в qs. Хотя использование list оценивает набор запросов, оно оценивает не исходный набор запросов, а производный набор запросов. Эта оценка запускает запрос SQL для получения только полей id, не тратя время на извлечение других полей.

Ответ 5

Вы можете сделать это с помощью 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