2009-11-07 11 views
5

Mam stronę opartą na obiekcie modelu i chcę mieć linki do poprzedniej i następnej strony. Nie podoba mi się moje obecne rozwiązanie, ponieważ wymaga oceny całego zestawu zapytań (aby uzyskać listę ids), a następnie dwóch kolejnych zapytań get. Z pewnością jest sposób, w jaki można to zrobić za jednym razem?Jak mogę uzyskać poprzednie i następne obiekty z przefiltrowanego, uporządkowanego zestawu pytań?

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) 

Porządek jest zdefiniowany w modelu, więc nie muszą być traktowane tutaj, ale należy pamiętać, że nie można przyjąć, że identyfikatory są sekwencyjne.

Odpowiedz

8

Brzmi jak coś, do czego Paginator ustawił wartość progową równą 1.

# 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 i here.

+1

Dzięki, miałem niejasno świadomy paginator, ale nie zrozumiałem, że mogę go używać tak (tj progu 1, w efekcie tylko owijanie queryset w obiekcie paginator za pomocą metod 'has_next()', 'has_previous()'). Jedyne, czego mi brakuje to to, że nie zaczynam od początku zakresu paginatora, ale wygląda na to, że mogę to uzyskać za pomocą 'p.object_list.index (start_page)'. –

+1

To nie działało dobrze dla mnie. Klasa Paginator naprawdę nie jest stworzona do przechodzenia przez obiekty. –

1

Jestem nowym Python i Django, więc może mój kod nie jest optymalna, ale to sprawdzić:

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) 

oraz mając coś takiego:

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, 
    }) 

zdecydowanie nie optymalna dla "ciężkich" zapytań, ale w większości przypadków działa jak czar. :)

1

Zapoznaj się z django-next-prev, napisałem go, aby rozwiązać ten dokładny problem. W tym przypadku:

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) 
Powiązane problemy