Pagination¶
Django fournit des méthodes de haut et de bas niveau pour vous aider à effectuer de la pagination de données, c’est-à-dire des données qui sont partagées en plusieurs pages, avec des liens « Précédent/Suivant ».
La classe Paginator
¶
Sous le capot, toutes les méthodes de pagination utilisent la classe Paginator
. Elle fait tout le travail de la division de l’objet QuerySet
en objets Page
.
Exemple¶
En donnant à Paginator
une liste d’objets ainsi que le nombre d’éléments souhaités sur chaque page, cette classe vous offre des méthodes pour accéder aux éléments des différentes pages :
>>> 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_iterator'>
>>> 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
Note
Remarquez que vous pouvez donner à Paginator
une liste/tuple, un QuerySet
Django ou tout autre objet possédant une méthode count()
ou __len__()
. Pour déterminer le nombre d’objets contenus dans l’objet transmis, Paginator
essaie d’abord d’appeler count()
et se rabat sur len()
si l’objet en question n’a pas de méthode count()
. Cela permet à des objets comme les QuerySet
de Django d’utiliser une méthode count()
plus efficace le cas échéant.
Pagination d’une vue ListView
¶
django.views.generic.list.ListView
offre la possibilité native de paginer la liste à afficher. Cela se fait en ajoutant un attribut paginate_by
à la classe de vue, par exemple
from django.views.generic import ListView
from myapp.models import Contact
class ContactListView(ListView):
paginate_by = 2
model = Contact
Ceci limite le nombre d’objets par page et ajoute les variables paginator
et page_obj
au contexte. Pour permettre aux utilisateurs de naviguer entre les pages, ajoutez dans le gabarit des liens vers les pages suivantes et précédentes, comme ceci :
{% 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>
Utilisation de Paginator
dans une fonction de vue¶
Voici un exemple d’utilisation de Paginator
dans une fonction de vue afin de paginer une requête
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})
Dans le gabarit list.html
, vous pouvez inclure des liens de navigation entre les pages de la même façon que dans le gabarit de la vue ListView
ci-dessus.