[Django]-Get the index of an element in a queryset

24👍

QuerySets in Django are actually generators, not lists (for further details, see Django documentation on QuerySets).
As such, there is no shortcut to get the index of an element, and I think a plain iteration is the best way to do it.

For starter, I would implement your requirement in the simplest way possible (like iterating); if you really have performance issues, then I would use some different approach, like building a queryset with a smaller amount of fields, or whatever.
In any case, the idea is to leave such tricks as late as possible, when you definitely knows you need them.
Update: You may want to use directly some SQL statement to get the rownumber (something lie . However, Django’s ORM does not support this natively and you have to use a raw SQL query (see documentation). I think this could be the best option, but again – only if you really see a real performance issue.

👤rob

68👍

If you’re already iterating over the queryset and just want to know the index of the element you’re currently on, the compact and probably the most efficient solution is:

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

However, don’t use this if you have a queryset and an object obtained by some unrelated means, and want to learn the position of this object in the queryset (if it’s even there).

57👍

If you just want to know where you object sits amongst all others (e.g. when determining rank), you can do it quickly by counting the objects before you:

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

25👍

Assuming for the purpose of illustration that your models are standard with a primary key id, then evaluating

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

will find the index of obj in qs. While the use of list evaluates the queryset, it evaluates not the original queryset but a derived queryset. This evaluation runs a SQL query to get the id fields only, not wasting time fetching other fields.

9👍

It’s possible for a simple pythonic way to query the index of an element in a queryset:

(*qs,).index(instance)

This answer will unpack the queryset into a list, then use the inbuilt Python index function to determine it’s position.

5👍

You can do this using queryset.extra(…) and some raw SQL like so:

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
👤Jiaaro

Leave a comment