Sidindelning¶
Django tillhandahåller hög- och lågnivåmetoder för att hjälpa dig att hantera paginerad data - det vill säga data som är uppdelad på flera sidor, med ”Föregående/Nästa”-länkar.
Klassen ”Paginator¶
Under huven använder alla metoder för paginering Paginator-klassen. Den gör allt det tunga arbetet med att faktiskt dela upp en QuerySet i Page-objekt.
Exempel¶
Ge Paginator en lista med objekt, plus det antal objekt du vill ha på varje sida, så ger den dig metoder för att komma åt objekten för varje sida:
>>> from django.core.paginator import Paginator
>>> objects = ["john", "paul", "george", "ringo"]
>>> p = Paginator(objects, 2)
>>> p.count
4
>>> p.num_pages
2
>>> type(p.page_range)
<class 'range'>
>>> p.page_range
range(1, 3)
>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']
>>> page2 = p.page(2)
>>> page2.object_list
['george', 'ringo']
>>> page2.has_next()
False
>>> page2.has_previous()
True
>>> page2.has_other_pages()
True
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number()
1
>>> page2.start_index() # The 1-based index of the first item on this page
3
>>> page2.end_index() # The 1-based index of the last item on this page
4
>>> p.page(0)
Traceback (most recent call last):
...
EmptyPage: That page number is less than 1
>>> p.page(3)
Traceback (most recent call last):
...
EmptyPage: That page contains no results
Observera
Observera att du kan ge Paginator en lista/tuple, en Django QuerySet eller något annat objekt med en count() eller __len__() metod. När Paginator bestämmer antalet objekt som ingår i det passerade objektet, kommer Paginator först att försöka anropa count(), och sedan fallbacka till att använda len() om det passerade objektet inte har någon count() metod. Detta gör att objekt som Djangos QuerySet kan använda en mer effektiv count()-metod när den är tillgänglig.
Paginering av en ListView¶
django.views.generic.list.ListView tillhandahåller ett inbyggt sätt att paginera den visade listan. Du kan göra detta genom att lägga till ett paginate_by-attribut till din vyklass, till exempel:
from django.views.generic import ListView
from myapp.models import Contact
class ContactListView(ListView):
paginate_by = 2
model = Contact
Detta begränsar antalet objekt per sida och lägger till en paginator och page_obj till context. För att tillåta dina användare att navigera mellan sidor, lägg till länkar till nästa och föregående sida, i din mall så här:
{% for contact in page_obj %}
{# Each "contact" is a Contact model object. #}
{{ contact.full_name|upper }}<br>
...
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">« first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
{% endif %}
</span>
</div>
Använda Paginator i en vyfunktion¶
Här är ett exempel där Paginator används i en vyfunktion för att paginera en frågeuppsättning:
from django.core.paginator import Paginator
from django.shortcuts import render
from myapp.models import Contact
def listing(request):
contact_list = Contact.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page.
page_number = request.GET.get("page")
page_obj = paginator.get_page(page_number)
return render(request, "list.html", {"page_obj": page_obj})
I mallen list.html kan du inkludera navigering mellan sidor på samma sätt som i mallen för ListView ovan.