What's the cleanest way of counting the iteration of a queryset loop?

Viewed 48

I need to loop through a queryset and put the objects into a dictionary along with the sequence number, i, in which they appear in the queryset. However a Python for loop doesn't seem to provide a sequence number. Therefore I've had to create my own variable i and increment it with each loop. I've done something similar to this, is this the cleanest solution?

ledgers = Ledger.objects.all()
i = 0

for ledger in ledgers:
    print('Ledger no '+str(i)+' is '+ledger.name)
    i += 1
2 Answers

enumerate(…) [Python-doc] is designed for that:

ledgers = Ledger.objects.all()

for i, ledger in enumerate(ledgers):
    print(f'Ledger no {i} is {ledger.name}')

This is not exactly the answer to your question.

If you'd need the index afterwards at the QuerySet, you can annotate it like that:

from django.db.models import Window, F

ledgers_qs = Ledger.objects.annotate(index=Window(expression=DenseRank(), order_by=F('id').desc()))

# You can iterate over the object indexes and names
for index, name in ledgers_qs.values_list('index', 'name'):
    print('Ledger no '+str(i)+' is '+ledger.name)
    i += 1

# You can make further QuerySet operations if needed
# because ledgers is a QuerySet with annotated indexes:
ledgers_qs.filter(index__lt=5, name__contains='foo')

With that you get a queryset that you can use for further database operations.


Why did I create this answer?

Because it is often better to work with QuerySet's if possible to be able to enhance the existing code structure without limitations.

DenseRank

Related