Brenden
Brenden

Reputation: 8774

Django find item in queryset and get next

I'm trying to take an object, look up a queryset, find the item in that queryset, and find the next one.

@property
def next_object_url(self):
    contacts = Model.objects.filter(owner=self.owner).order_by('-date')
    place_in_query = list(contacts.values_list('id', flat=True)).index(self.id)
    next_contact = contacts[place_in_query + 1]

When I add this to the model and run it, here's what I get for each variable for one instance.

CURRENT = Current Object
NEXT = Next Object

contacts.count = 1114
self.id = 3533 #This is CURRENT.id
place_in_query = 36
contacts[place_in_query] = NEXT
next_contact = CURRENT

What am i missing / what dumb mistake am i making?

Upvotes: 1

Views: 3356

Answers (1)

Laurent LAPORTE
Laurent LAPORTE

Reputation: 23002

In your function, contacts is a QuerySet. The actual objets are not fetched in the line:

contacts = Model.objects.filter(owner=self.owner).order_by('-date')

because you don’t use a function like list(), you don’t iterate the QuerySet yet... It is evaluated later. This is probably the reason of your problem.

Since you need to search an ID in the list of contacts and the find the next object in that list, I think there is no way but fetch all the contact and use a classic Python loop to find yours objects.

@property
def next_object_url(self):
    contacts = list(Model.objects.filter(owner=self.owner).order_by('-date').all())
    for curr_contact, next_contact in zip(contacts[:-1], contacts[1:]):
        if curr_contact.id == self.id:
            return next_contact
    else:
        # not found
        raise ContactNotFoundError(self.id)

Another solution would be to change your database model in order to add a notion of previous/next contact at database level…

Upvotes: 2

Related Questions