简体   繁体   中英

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?

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…

I'm not sure why your code doesn't work, but I think there is a better approach, use a raw query:

@property
def next_object_url(self):
    contacts = Model.objects.raw(f'''
      SELECT 
      t1.id, 
      DATEDIFF((SELECT t2.date FROM table t2 WHERE t2.id = {self.id}), t1.date) as d
      from table t1
      ORDER BY d asc
      LIMIT 2
    ''')

This is completely untested, and might have to be adapted for your specific database. Hopefully your database supports DATEDIFF !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM