Django fournit quelques classes qui aident à 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 ». Ces classes se trouvent dans django/core/paginator.py
.
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) # `<type 'rangeiterator'>` in Python 2.
<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.
Paginator
dans une vue¶Voici un exemple un peu plus complexe qui utilise Paginator
dans une vue pour paginer un résultat de requête. Nous présentons à la fois la vue et le gabarit correspondant pour vous montrer comment afficher les résultats. Cet exemple part du principe qu’il existe un modèle Contacts
qui a déjà été importé.
La fonction de vue ressemble à ceci :
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render
def listing(request):
contact_list = Contacts.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page
page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
contacts = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
contacts = paginator.page(paginator.num_pages)
return render(request, 'list.html', {'contacts': contacts})
Dans le gabarit list.html
, il est nécessaire d’inclure des éléments de navigation pour passer d’une page à l’autre, ainsi que des informations utiles sur les objets eux-mêmes :
{% for contact in contacts %}
{# Each "contact" is a Contact model object. #}
{{ contact.full_name|upper }}<br />
...
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
<a href="?page={{ contacts.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>
{% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}">next</a>
{% endif %}
</span>
</div>
Paginator
¶Voici le constructeur de la classe Paginator
:
object_list
A list, tuple, QuerySet
, or other sliceable object with a count()
or __len__()
method. For consistent pagination, QuerySet
s should
be ordered, e.g. with an order_by()
clause or with a default ordering
on the
model.
Performance issues paginating large QuerySet
s
If you’re using a QuerySet
with a very large number of items,
requesting high page numbers might be slow on some databases, because
the resulting LIMIT
/OFFSET
query needs to count the number of
OFFSET
records which takes longer as the page number gets higher.
per_page
Le nombre maximum d’éléments à inclure dans une page, sans tenir compte des orphelins (voir le paramètre facultatif orphans
ci-dessous).
orphans
Le nombre minimum d’éléments autorisés sur la dernière page, la valeur par défaut étant zéro. Utilisez ce paramètre lorsque vous ne souhaitez pas de dernière page avec très peu d’éléments. Lorsque la dernière page ne contient que le nombre orphans
d’éléments ou moins, ces éléments sont alors ajoutés à la page précédente (qui devient la dernière page) au lieu de les laisser seuls sur une page. Par exemple, avec 23 éléments, per_page=10
et orphans=3
, il y aura deux pages ; la première avec 10 éléments et la seconde (et dernière) avec 13 éléments.
allow_empty_first_page
Indique si la première page peut être vide. Avec la valeur False
et une liste object_list
vide, une erreur EmptyPage
sera produite.
Paginator.
page
(number)[source]¶Renvoie un objet Page
correspondant à l’index number
(commençant à 1). Si le numéro de page indiqué n’existe pas, une exception InvalidPage
est levée.
Paginator.
count
¶Le nombre total d’objets sur toutes les pages.
Note
Lors de la détermination du nombre d’objets contenus dans object_list
, Paginator
essaie d’abord d’appeler object_list.count()
. Si object_list
n’a pas de méthode count()
, Paginator
se rabat sur len(object_list)
. Cela permet à des objets comme les QuerySet
de Django d’utiliser une méthode count()
plus efficace le cas échéant.
Paginator.
num_pages
¶Le nombre total de pages.
Paginator.
page_range
¶Une itération d’intervalle de numéros de pages commençant à 1, par ex. produisant [1, 2, 3, 4]
.
Dans les anciennes versions, page_range
renvoyait une liste au lieu d’une itération.
InvalidPage
¶InvalidPage
[source]¶Une classe de base pour les exceptions levées lorsqu’un paginateur reçoit un numéro de page non valable.
La méthode Paginator.page()
lève une exception quand la page demandée n’est pas valable (par ex. ce n’est pas un nombre entier) ou quand elle ne contient aucun objet. Il est généralement suffisant d’intercepter l’exception InvalidPage
, mais si vous souhaitez plus de finesse, vous pouvez intercepter l’une des exceptions suivantes :
PageNotAnInteger
[source]¶Levée lorsque page()
reçoit une valeur qui n’est pas un nombre entier.
EmptyPage
[source]¶Levée lorsque page()
reçoit une valeur valable, mais que la page en question ne contient pas d’objet.
Ces deux exceptions sont des sous-classes de InvalidPage
, il est donc possible de les intercepter par une simple ligne except InvalidPage
.
Page
¶Les objets Page
ne sont normalement pas construits manuellement, mais plutôt obtenus en appelant Paginator.page()
.
Page
(object_list, number, paginator)[source]¶Une page se comporte comme un liste de Page.object_list
lorsqu’on lui applique len()
ou qu’on effectue une itération sur elle.
Page.
next_page_number
()[source]¶Renvoie le prochain numéro de page. Génère InvalidPage
s’il n’y a pas de page suivante.
Page.
previous_page_number
()[source]¶Renvoie le numéro de page précédent. Génère InvalidPage
s’il n’y a pas de page précédente.
Page.
start_index
()[source]¶Renvoie l’index (commençant par 1) du premier objet de la page, relatif à tous les autres objets de la liste du paginateur. Par exemple, lors de la pagination d’une liste de 5 objets par groupes de 2, la méthode start_index()
de la deuxième page renverrait 3
.
Page.
end_index
()[source]¶Renvoie l’index (commençant par 1) du dernier objet de la page, relatif à tous les autres objets de la liste du paginateur. Par exemple, lors de la pagination d’une liste de 5 objets par groupes de 2, la méthode end_index()
de la deuxième page renverrait 4
.
août 01, 2016