Пагинация
источник:
pagination.py
Пагинация
Django предоставляет несколько классов, которые помогают вам управлять постраничными данными - то есть данными, разделенными на несколько страниц, со ссылками "Предыдущая/Следующая".
DRF включает поддержку настраиваемых стилей пагинации. Это позволяет изменять, как большие наборы результатов разбиваются на отдельные страницы данных.
API пагинации может поддерживать любую из этих функций:
Ссылки пагинации, которые предоставляются как часть содержимого ответа.
Ссылки пагинации, включенные в заголовки ответа, такие как
Content-Range
илиLink
.
В настоящее время все встроенные стили используют ссылки, включенные как часть содержимого ответа. Этот стиль более доступен при использовании API с возможностью просмотра.
Пагинация выполняется автоматически, только если вы используете общие представления или наборы представлений. Если вы используете обычное APIView
, вам нужно будет самостоятельно обратиться к API пагинации, чтобы убедиться, что вы возвращаете ответ с пагинацией. Пример смотрите в исходном коде классов mixins.ListModelMixin
и generics.GenericAPIView
.
Пагинацию можно отключить, установив для класса пагинации значение None
.
Установка стиля пагинации
Стиль пагинации можно задать глобально, используя ключи настройки DEFAULT_PAGINATION_CLASS
и PAGE_SIZE
. Например, чтобы использовать встроенную пагинацию с ограничением/смещением, вы должны сделать следующее:
Обратите внимание, что необходимо задать как класс пагинации, так и размер страницы, которая будет использоваться. По умолчанию и DEFAULT_PAGINATION_CLASS
, и PAGE_SIZE
имеют значение None
.
Вы также можете установить класс пагинации для отдельного представления с помощью атрибута pagination_class
. Обычно вы хотите использовать один и тот же стиль пагинации во всем API, хотя вы можете захотеть варьировать отдельные аспекты пагинации, такие как размер страницы по умолчанию или максимальный размер страницы, на основе каждого представления.
Изменение стиля пагинации
Если вы хотите изменить определенные аспекты стиля пагинации, вам нужно переопределить один из классов пагинации и установить атрибуты, которые вы хотите изменить.
Затем вы можете применить ваш новый стиль к представлению с помощью атрибута pagination_class
:
Или примените стиль глобально, используя ключ настройки DEFAULT_PAGINATION_CLASS
. Например:
Описание API
PageNumberPagination
Этот стиль пагинации принимает номер страницы с одним номером в параметрах запроса.
Запрос:
Ответ:
Настройка
Чтобы включить стиль PageNumberPagination
глобально, используйте следующую конфигурацию и установите PAGE_SIZE
по желанию:
В подклассах GenericAPIView
вы также можете установить атрибут pagination_class
для выбора PageNumberPagination
на основе каждого вида.
Конфигурация
Класс PageNumberPagination
включает ряд атрибутов, которые могут быть переопределены для изменения стиля пагинации.
Чтобы установить эти атрибуты, необходимо переопределить класс PageNumberPagination
, а затем включить свой собственный класс пагинации, как указано выше.
django_paginator_class
- Класс Django Paginator, который будет использоваться. По умолчанию этоdjango.core.paginator.Paginator
, что должно быть хорошо для большинства случаев использования.page_size
- Числовое значение, указывающее размер страницы. Если установлено, оно отменяет настройкуPAGE_SIZE
. По умолчанию имеет то же значение, что и ключ настройкиPAGE_SIZE
.page_query_param
- Строковое значение, указывающее имя параметра запроса, который будет использоваться для управления пагинацией.page_size_query_param
- Если установлено, это строковое значение, указывающее имя параметра запроса, который позволяет клиенту устанавливать размер страницы на основе каждого запроса. По умолчаниюNone
, что означает, что клиент не может контролировать размер запрашиваемой страницы.max_page_size
- Если установлено, это числовое значение, указывающее на максимально допустимый размер запрашиваемой страницы. Этот атрибут действителен, только еслиpage_size_query_param
также установлен.last_page_strings
- Список или кортеж строковых значений, указывающих на значения, которые могут быть использованы сpage_query_param
для запроса последней страницы в наборе. По умолчанию('last',)
template
- Имя шаблона для использования при отображении элементов управления пагинацией в Web-интерфейсе API. Может быть переопределено для изменения стиля рендеринга или установлено вNone
для полного отключения HTML элементов управления пагинацией. По умолчанию используется"rest_framework/pagination/numbers.html"
.
LimitOffsetPagination
Этот стиль пагинации повторяет синтаксис, используемый при поиске нескольких записей в базе данных. Клиент включает в себя как 'limit'
, так и параметр запроса 'offset'
. Лимит указывает на максимальное количество возвращаемых элементов и эквивалентен page_size
в других стилях. Смещение указывает начальную позицию запроса по отношению к полному набору непагинированных элементов.
Запрос:
Ответ:
Подключение
Чтобы включить стиль LimitOffsetPagination
глобально, используйте следующую конфигурацию:
По желанию вы также можете задать ключ PAGE_SIZE
. Если параметр PAGE_SIZE
также используется, то параметр запроса limit
будет необязательным и может быть опущен клиентом.
В подклассах GenericAPIView
вы также можете установить атрибут pagination_class
для выбора LimitOffsetPagination
для каждого представления.
Настройка
Класс LimitOffsetPagination
включает ряд атрибутов, которые могут быть переопределены для изменения стиля пагинации.
Чтобы установить эти атрибуты, вы должны переопределить класс LimitOffsetPagination
, а затем включить свой собственный класс пагинации, как указано выше.
default_limit
- Числовое значение, указывающее предел, который следует использовать, если он не указан клиентом в параметре запроса. По умолчанию имеет то же значение, что и ключ настройкиPAGE_SIZE
.limit_query_param
- Строковое значение, указывающее имя параметра запроса "limit". По умолчанию имеет значение'limit'
.offset_query_param
- Строковое значение, указывающее имя параметра запроса "offset". По умолчанию имеет значение'offset'
.max_limit
- Если установлено, то это числовое значение, указывающее на максимально допустимый лимит, который может быть запрошен клиентом. По умолчаниюNone
.template
- Имя шаблона, который будет использоваться при отображении элементов управления пагинацией в Web-интерфейсе API. Может быть переопределено для изменения стиля рендеринга или установлено вNone
для полного отключения HTML элементов управления пагинацией. По умолчанию используется"rest_framework/pagination/numbers.html"
.
CursorPagination
Пагинация на основе курсора представляет непрозрачный индикатор cursor
, который клиент может использовать для просмотра набора результатов. Этот стиль пагинации представляет только элементы управления перемоткой вперед и назад и не позволяет клиенту переходить к произвольным позициям.
Пагинация на основе курсора требует наличия уникального, неизменного порядка следования элементов в наборе результатов. Обычно таким упорядочиванием может быть временная метка создания записей, так как она представляет собой последовательный порядок для постраничного просмотра.
Пагинация на основе курсора является более сложной, чем другие схемы. Она также требует, чтобы набор результатов представлял фиксированный порядок, и не позволяет клиенту произвольно индексировать набор результатов. Однако она обеспечивает следующие преимущества:
Обеспечивает последовательное представление пагинации. При правильном использовании
CursorPagination
гарантирует, что клиент никогда не увидит один и тот же элемент дважды при листании записей, даже если новые элементы вставляются другими клиентами во время процесса пагинации.Поддержка использования с очень большими наборами данных. При работе с очень большими наборами данных пагинация с использованием стилей пагинации на основе смещения может стать неэффективной или непригодной для использования. Вместо этого схемы пагинации на основе курсора имеют свойства фиксированного времени и не замедляются при увеличении размера набора данных.
Подробности и ограничения
Правильное использование пагинации на основе курсора требует некоторого внимания к деталям. Вам нужно подумать о том, в каком порядке вы хотите применять схему. По умолчанию используется порядок по "-created"
. Это предполагает, что в экземплярах модели должно быть поле временной метки "created", и будет представлено постраничное представление в стиле "временной шкалы", где первыми будут самые последние добавленные элементы.
Вы можете изменить порядок, переопределив атрибут 'ordering'
класса пагинации, или используя класс фильтра OrderingFilter
вместе с CursorPagination
. При использовании OrderingFilter
следует тщательно продумать ограничение полей, по которым пользователь может делать заказ.
Правильное использование пагинации курсора должно иметь поле упорядочивания, которое удовлетворяет следующим требованиям:
Должно быть неизменным значением, таким как временная метка, slug или другое поле, которое устанавливается только один раз, при создании.
Должно быть уникальным или почти уникальным. Хорошим примером являются временные метки с точностью до миллисекунды. Эта реализация пагинации курсора использует интеллектуальный стиль "позиция плюс смещение", что позволяет ей правильно поддерживать не строго уникальные значения в качестве упорядочивания.
Должно быть не нулевым значением, которое можно принудительно преобразовать в строку.
Не должно быть плавающей точкой. Ошибки точности легко приводят к неправильным результатам. Совет: используйте вместо этого десятичные числа. (Если у вас уже есть поле с плавающей запятой и вам нужно сделать постраничную запись по нему, можно воспользоваться командой [пример подкласса
CursorPagination
, который использует десятичные числа для ограничения точности, доступен здесь] (https://gist.github.com/keturn/8bc88525a183fd41c73ffb729b8865be#file-fpcursorpagination-py).)Поле должно иметь индекс базы данных.
Использование поля упорядочивания, которое не удовлетворяет этим ограничениям, как правило, будет работать, но вы потеряете некоторые преимущества пагинации курсора.
Для получения более подробной технической информации о реализации, которую мы используем для пагинации курсоров, в статье "Building cursors for the Disqus API" блога дается хороший обзор основного подхода.
Подключение
Чтобы включить стиль CursorPagination
глобально, используйте следующую конфигурацию, изменяя PAGE_SIZE
по желанию:
В подклассах GenericAPIView
вы также можете установить атрибут pagination_class
для выбора CursorPagination
на основе каждого вида.
Настройка
Класс CursorPagination
включает ряд атрибутов, которые могут быть переопределены для изменения стиля пагинации.
Чтобы установить эти атрибуты, необходимо переопределить класс CursorPagination
, а затем включить свой собственный класс пагинации, как указано выше.
page_size
- числовое значение, указывающее размер страницы. Если установлено, оно отменяет настройкуPAGE_SIZE
. По умолчанию имеет то же значение, что и ключ настройкиPAGE_SIZE
.cursor_query_param
- Строковое значение, указывающее имя параметра запроса "cursor". По умолчанию'cursor'
.orderering
- Это должна быть строка или список строк, указывающих на поле, к которому будет применяться пагинация на основе курсора. Например:ordering = 'slug'
. По умолчанию используется-created
. Это значение также может быть переопределено с помощьюOrderingFilter
в представлении.template
- Имя шаблона, который будет использоваться при отображении элементов управления пагинацией в API просмотра. Может быть переопределено для изменения стиля рендеринга или установлено вNone
для полного отключения HTML элементов управления пагинацией. По умолчанию используется"rest_framework/pagination/previous_and_next.html"
.
Пользовательские стили пагинации
Чтобы создать собственный класс сериализатора пагинации, необходимо унаследовать подкласс pagination.BasePagination
, переопределить методы paginate_queryset(self, queryset, request, view=None)
и get_paginated_response(self, data)
:
Метод
paginate_queryset
передается начальному кверисету и должен возвращать итерируемый объект. Этот объект содержит только данные запрашиваемой страницы.Метод
get_paginated_response
передается сериализованным данным страницы и должен возвращать экземплярResponse
.
Обратите внимание, что метод paginate_queryset
может установить состояние экземпляра пагинации, которое впоследствии может быть использовано методом get_paginated_response
.
Пример
Предположим, мы хотим заменить стандартный стиль вывода пагинации на модифицированный формат, который включает следующую и предыдущую ссылки во вложенном ключе 'links'
. Мы можем указать пользовательский класс пагинации следующим образом:
Затем нам нужно будет установить пользовательский класс в нашей конфигурации:
Обратите внимание, что если вам важно, как порядок ключей отображается в ответах в Web-интерфейсе API, вы можете использовать OrderedDict
при построении тела постраничных ответов, но это необязательно.
Использование вашего пользовательского класса пагинации
Чтобы ваш пользовательский класс пагинации использовался по умолчанию, используйте параметр DEFAULT_PAGINATION_CLASS
:
Ответы API для конечных точек списка теперь будут включать заголовок Link
, вместо того чтобы, например, включать ссылки пагинации как часть тела ответа:
Настраиваемый стиль пагинации с использованием заголовка Link
.
Элементы управления пагинацией HTML
По умолчанию использование классов пагинации приводит к отображению элементов управления пагинацией HTML в Web-интерфейсе API. Существует два встроенных стиля отображения. Классы PageNumberPagination
и LimitOffsetPagination
отображают список номеров страниц с предыдущим и следующим элементами управления. Класс CursorPagination
отображает более простой стиль, в котором отображаются только предыдущий и следующий элементы управления.
Настройка элементов управления
Вы можете переопределить шаблоны, которые отображают элементы управления пагинацией HTML. Есть два встроенных стиля:
'rest_framework/pagination/numbers.html'
'rest_framework/pagination/previous_and_next.html'
Предоставление шаблона с любым из этих путей в глобальном каталоге шаблонов переопределит рендеринг по умолчанию для соответствующих классов пагинации.
В качестве альтернативы вы можете полностью отключить элементы управления HTML-пагинацией, создав подкласс одного из существующих классов и установив template = None
в качестве атрибута класса. Затем вам нужно будет настроить ключ параметров DEFAULT_PAGINATION_CLASS
, чтобы использовать ваш пользовательский класс в качестве стиля пагинации по умолчанию.
Низкоуровневый API
Низкоуровневый API для определения того, должен ли класс пагинации отображать элементы управления или нет, раскрывается как атрибут display_page_controls
на экземпляре пагинации. Пользовательские классы пагинации должны быть установлены в True
в методе paginate_queryset
, если они требуют отображения элементов управления пагинацией HTML.
Методы .to_html()
и .get_html_context()
также могут быть переопределены в пользовательском классе пагинации для дальнейшей настройки отображения элементов управления.
Пакеты сторонних производителей
Также доступны следующие пакеты сторонних производителей.
DRF-extensions
Пакет DRF-extensions
включает класс-миксин PaginateByMaxMixin
, который позволяет вашим клиентам API указывать ?page_size=max
для получения максимально допустимого размера страницы.
drf-proxy-pagination
Пакет drf-proxy-pagination
включает класс ProxyPagination
, который позволяет выбирать класс пагинации с помощью параметра запроса.
link-header-pagination
Пакет django-rest-framework-link-header-pagination
включает класс LinkHeaderPagination
, который обеспечивает пагинацию через HTTP-заголовок Link
, как описано в документации GitHub REST API.
Last updated