Django предоставляет несколько классов, которые помогают реализовать постраничный вывод данных, т.е. данных, распределённых на несколько страниц с ссылками «Предыдущая/Следующая». Эти классы располагаются в django/core/paginator.py.
Передайте в класс Paginator список объектов и количество элементов, которое надо отображать на странице. Класс предоставит методы для доступа к элементам каждой страницы:
>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2)
>>> p.count
4
>>> p.num_pages
2
>>> p.page_range
[1, 2]
>>> 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()
3
>>> 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
Примечание
Следует отметить, что вы можете передать классу Paginator список/кортеж, QuerySet Django или любой другой объект, который имеет методы count() или __len__(). Для определения количества объектов, содержащихся в переданном объекте, Paginator сначала попробует вызвать метод count(), затем, при его отсутствии, вызывает len(). Такой подход позволяет объектам, подобным QuerySet, более эффективно использовать метод count() при его наличии.
Здесь приведён более сложный пример использования класса Paginator в представлении для постраничного вывода результатов запроса. Мы предоставили представление и его шаблон, чтобы показать, как вы можете отображать результаты. Данный пример предполагает наличие у вас модели Contacts, которая уже была импортирована.
Функция представления может выглядеть так:
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
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_to_response('list.html', {"contacts": contacts})
В шаблоне list.html подключен блок навигации по страницам:
{% 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 есть конструктор:
Возвращает объект Page по переданному индексу (начинается с единицы). Вызывает исключение InvalidPage, если указанная страница не существует.
Общее количество объектов, распределенных по всем страницам.
Примечание
При определении количества объектов, содержащихся в object_list, Paginator сначала пробует вызвать object_list.count(). Если у object_list нет метода count(), то Paginator попробует вызвать len(object_list). Такой подход позволяет объектам, подобным QuerySet Django, более эффективно использовать метод count() при его наличии.
Общее количество страниц.
Диапазон номеров страниц, начинающийся с единицы, т.е., [1, 2, 3, 4].
Базовый класс для исключений, которые вызываются когда происходит запрос страницы по несуществующему номеру.
Метод Paginator.page() вызывает исключение, если номер запрошенной страницы является неправильным (т.е., не представлен целым числом) или не содержит объектов. В общем случае, достаточно обрабатывать исключение InvalidPage, но если вам требуется более тонкий контроль, вы можете отрабатывать следующие исключения:
Вызывается, если page() получает значение, которое не является целым числом.
Вызывается, если page() получает правильное значение, но для указанной страницы нет объектов.
Эти исключения являются потомками класса InvalidPage, таким образом, вы можете обрабатывать их с помощью простого except InvalidPage.
Обычно создавать объекты Page вручную не требуется, так как вы получаете их с помощью метода Paginator.page().
Возвращает True, если следующая страница существует.
Возвращает True, если предыдущая страница существует.
Возвращает True, если существует следующая или предыдущая страница.
Возвращает номер следующей страницы. Следует отметить, что «интеллекта» здесь нет и номер будет возвращён даже в случае, когда следующая страница не существует.
Возвращает номер предыдущей страницы. Следует отметить, что «интеллекта» здесь нет и номер будет возвращён даже в случае, когда предыдущая страница не существует.
Возвращает индекс (начинается с единицы) первого объекта на странице относительно списка всех объектов. Например, для списка из пяти объектов при отображении двух объектов на странице, то для второй страницы метод start_index() вернёт 3.
Возвращает индекс (начинается с единицы) последнего объекта на странице относительно списка всех объектов. Например, для списка из пяти объектов при отображении двух объектов на странице, то для второй страницы метод end_index() вернёт 4.
Aug 21, 2013