Пагинация
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 >>> 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
Примечание
Обратите внимание, что вы можете передать Paginator список/кортеж, Django QuerySet, или любой другой объект с методом count() или __len__(). При определении количества объектов, содержащихся в переданном объекте, Paginator сначала попробует вызвать count(), а затем перейдет к использованию len(), если у переданного объекта нет метода count(). Это позволяет таким объектам, как Django QuerySet, использовать более эффективный метод count() при его наличии.
Использование Paginator в представлении
Вот немного более сложный пример использования Paginator в представлении для постраничной обработки набора запросов. Мы предоставим как представление, так и сопутствующий шаблон, чтобы показать, как можно отображать результаты. Этот пример предполагает, что у вас есть модель Contacts, которая уже импортирована.
Функция представления выглядит следующим образом:
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})
В шаблоне 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 объекты
Класс Paginator имеет следующий конструктор:
-
class Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True)[source]
Необходимые аргументы
-
object_list -
Список, кортеж,
QuerySet, или другой объект с возможностью срезов, имеющий методcount()или__len__(). Для согласованной пагинации объекты должны быть упорядочены, например, с помощьюorder_by()или с помощью свойстваorderingв модели.Проблемы производительности при пагинации больших наборов запросов
Если вы используете
QuerySetс очень большим количеством элементов, запрос высоких номеров страниц может быть медленным на некоторых базах данных, так как полученныйLIMIT/OFFSETзапрос должен подсчитать количествоOFFSETзаписей, что занимает больше времени по мере увеличения номера страницы. -
per_page - Максимальное количество элементов на странице, не включая «осиротевшие» (см. необязательный аргумент
orphansниже).
Необязательные аргументы
-
orphans - Используется, когда вы не хотите иметь последнюю страницу с очень небольшим количеством элементов. Если последняя страница обычно содержит количество элементов меньше или равно
orphans, эти элементы будут добавлены к предыдущей странице (которая станет последней), вместо того, чтобы оставлять их на отдельной странице. Например, с 23 элементами,per_page=10, иorphans=3, будет две страницы: первая страница с 10 элементами и вторая (последняя) страница с 13 элементами. По умолчаниюorphansравно нулю, что означает, что страницы никогда не объединяются, и последняя страница может содержать один элемент. -
allow_empty_first_page - Разрешено ли оставлять первую страницу пустой. Если
Falseиobject_listпуста, то будет поднято исключениеEmptyPage.
Методы
-
Paginator.page(number)[source] -
Возвращает объект
Pageс заданным индексом (1-основанный). Поднимает исключениеInvalidPage, если заданный номер страницы не существует.
Атрибуты
-
Paginator.count -
Общее количество объектов на всех страницах.
Примечание
При определении количества объектов, содержащихся в
object_list,Paginatorсначала попробует вызватьobject_list.count(). Если уobject_listнет методаcount(), тоPaginatorперейдет к использованиюlen(object_list). Это позволяет объектам, таким как DjangoQuerySet, использовать более эффективный методcount()при его наличии.
-
Paginator.num_pages -
Общее количество страниц.
-
Paginator.page_range -
Итератор диапазона номеров страниц (1-основанный), например, возвращающий
[1, 2, 3, 4].
Исключения InvalidPage
-
exception InvalidPage[source] -
Базовый класс исключений, выбрасываемых при передаче пагинатору некорректного номера страницы.
Метод Paginator.page() генерирует исключение, если запрошенная страница некорректна (то есть не является целым числом) или не содержит объектов. Обычно достаточно перехватить исключение InvalidPage, но если вам нужна большая детализация, вы можете перехватить любое из следующих исключений:
-
exception PageNotAnInteger[source] -
Сгенерировано, когда
page()принимает значение, которое не является целым числом.
-
exception EmptyPage[source] -
Выбрасывается, когда
page()принимает корректное значение, но на этой странице нет объектов.
Оба исключения являются подклассами InvalidPage, поэтому вы можете обработать их оба с помощью простого блока except InvalidPage.
Page объекты
Обычно вы не создаете объекты Page вручную — вы получаете их с помощью Paginator.page().
-
class Page(object_list, number, paginator)[source] -
Страница ведет себя как последовательность
Page.object_listпри использованииlen()или при непосредственном итерировании.
Методы
-
Page.has_next()[source] -
Возвращает
Trueесли существует следующая страница.
-
Page.has_previous()[source] -
Возвращает
Trueесли существует предыдущая страница.
-
Page.has_other_pages()[source] -
Возвращает
Trueесли существует следующая или предыдущая страница.
-
Page.next_page_number()[source] -
Возвращает номер следующей страницы. Выбрасывает
InvalidPage, если следующей страницы не существует.
-
Page.previous_page_number()[source] -
Возвращает номер предыдущей страницы. Выбрасывает
InvalidPage, если предыдущей страницы не существует.
-
Page.start_index()[source] -
Возвращает индекс первого объекта на странице, начиная с 1, относительно всего списка объектов в пагинаторе. Например, при разбиении списка из 5 объектов на страницы по 2 объекта на странице,
start_index()второй страницы вернёт3.
-
Page.end_index()[source] -
Возвращает индекс последнего объекта на странице, начиная с 1, относительно всего списка объектов в пагинаторе. Например, при разбиении списка из 5 объектов на страницы по 2 объекта на странице,
end_index()второй страницы вернёт4.
Атрибуты
-
Page.object_list -
Список объектов на этой странице.
-
Page.number -
Номер страницы (начиная с 1) для этой страницы.
-
Page.paginator -
Соответствующий объект
Paginator.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.11/topics/pagination/