Marconi
Marconi

Reputation: 3651

How to get next row on a django queryset?

I have a queryset with that will return several rows in it. One of the row has a slug "slug-456", how do I get to the next row after that row having the slug "slug-456" with respect to the current ordering the queryset have?

I can loop through the queryset and check if the current row has the slug "slug-456" and if it has take note that the next row is what I'm after, but Is there a more efficient way?

UPDATE: I did it this way:

id_list = list(qs.values_list('id', flat=True))
try:
    next_id = id_list[id_list.index(obj.id) + 1]
    obj = Object.objects.get(id=next_id)
except IndexError:
    pass

Upvotes: 9

Views: 12240

Answers (2)

Shawn Chin
Shawn Chin

Reputation: 86864

Querysets are generators so there isn't really a shortcut along the lines of qs[qs.indexof(slug="..")+1]. Any solution you come up with still require iterating through the queryset (at least till the target object).

As you mention, a possible way to do it would be to loop through the queryset and return the one right after the one with slug="slug-456".

You could of course take a more convoluted route and do something along the lines of:

# get slugs in order
sio = list(qs.objects.values_list('slug', flat=True))
target_slug = sio[sio.index(sio) + 1] # watch for KeyError
your_object = qs.objects.get(slug__exact=target_slug)

while amusing to write, this is unlikely to give any performance benefits (unless your model has many fields in which case iterating through the output of values_list() first might be beneficial).

Related answer: Get the index of an element in a queryset.

Upvotes: 6

Almad
Almad

Reputation: 5893

For py<2.6,

queryset.iterator().next()

For >= 2.6

next(queryset.iterator())

should do the trick

Upvotes: 11

Related Questions