2009-11-07 4 views
5

Ich habe eine Seite basierend auf einem Modellobjekt, und ich möchte Links zu den vorherigen und nächsten Seiten haben. Ich mag meine aktuelle Lösung nicht, weil sie das gesamte Abfrage-Set auswerten muss (um die ids Liste zu erhalten), und dann zwei weitere get Abfragen. Sicherlich gibt es eine Möglichkeit, dies in einem Durchgang zu machen?Wie kann ich vorherige und nächste Objekte aus einem gefilterten, geordneten Abfrage-Set abrufen?

def get_prev_and_next_page(current_page): 
    ids = list(Page.objects.values_list("id", flat=True)) 
    current_idx = ids.index(current_page.id) 
    prev_page = Page.objects.get(id=ids[current_idx-1]) 
    try: 
     next_page = Page.objects.get(id=ids[current_idx+1]) 
    except IndexError: 
     next_page = Page.objects.get(id=ids[0]) 
    return (prev_page, next_page) 

Sortierung wird im Modell definiert sind, so hier nicht behandelt werden muss, aber beachten Sie, dass man nicht davon ausgehen kann, dass ids sequentiell sind.

Antwort

8

Klingt nach etwas, das der Paginator auf 1 gesetzt hätte.

# Full query set... 
pages = Page.objects.filter(column=somevalue) 
p = Paginator(pages, 1) 

# Where next page would be something like... 
if p.has_next(): 
    p.page(p.number+1) 

Documentation here und here.

+1

Dank war ich vagee Kenntnis von der Paginator, hatte aber nicht bemerkt, dass ich es so, dass (dh mit einem Schwellenwert von 1, in der Tat nutzen könnte nur die queryset in einem Paginatorobjekt Einwickeln mit den 'has_next()', 'has_previous()' Methoden). Es fehlt nur, dass ich nicht am Anfang des Paginator-Bereichs beginne, aber es sieht so aus, als könnte ich das mit 'p.object_list.index (start_page)' erreichen. –

+1

Das endete nicht gut für mich. Die Paginator-Klasse ist wirklich nicht zum Durchqueren von Objekten geeignet. –

1

Ich bin neu in Python und Django, vielleicht mein Code nicht optimal ist, aber diese Besuche:

def get_prev_and_next_items(target, items): 
    ''' To get previous and next objects from QuerySet ''' 
    found = False 
    prev = None 
    next = None 
    for item in items: 
     if found: 
      next = item 
      break 
     if item.id == target.id: 
      found = True 
      continue 
     prev = item 
    return (prev, next) 

Und angesichts so ähnlich:

def organisation(request, organisation_id): 
    organisation = Organisation.objects.get(id=organisation_id) 
    ... 
    prev, next = get_prev_and_next_items(organisation, Organisation.objects.all().order_by('type')) 
    ... 
    return render_to_response('reference/organisation/organisation.html', { 
     'organisation': organisation, 
     'prev': prev, 
     'next': next, 
    }) 

Definitiv nicht optimal für «schwere» Suchanfragen, funktioniert aber in den meisten Fällen wie ein Zauber. :)

1

Check out django-next-prev, schrieb ich es genau dieses Problem zu lösen. In diesem Fall:

from next_prev import next_in_order, prev_in_order 

def get_prev_and_next_page(current_page): 
    page_qs = Page.objects.all() # this could be filtered, or ordered 
    prev_page = prev_in_order(current_page, page_qs) 
    next_page = prev_in_order(current_page, page_qs) 
    return (prev_page, next_page) 
Verwandte Themen