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 ContactList(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">&laquo; 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 &raquo;</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.

Back to Top