Добро пожаловать на очередное погружение в мир Django REST Framework! Сегодня мы поговорим о том, как с помощью пагинации эффективно управлять объемами данных, передаваемых через API. Если у вас когда-либо запрашивали данные из API и сервер выдал вам огромный список объектов (например, миллион строк), то вы, скорее всего, испытали боль, с которой мы сейчас будем бороться. В этой лекции вы узнаете, как настроить и использовать два популярных типа пагинации в DRF: PageNumberPagination и LimitOffsetPagination.
Что такое PageNumberPagination?
PageNumberPagination — это механизм, который делит ваши данные на страницы по принципу "номер страницы + количество объектов на странице". Например, если в базе данных у вас есть 50 записей, а на странице вы хотите отображать 10 объектов, то ваш API вернет 5 страниц.
Основные параметры PageNumberPagination:
page_size— определяет, сколько объектов будет возвращаться на одной странице.page_query_param— задаёт название параметра в запросе, который указывает номер страницы (по умолчанию этоpage).page_size_query_param— позволяет клиенту самостоятельно задавать количество объектов на странице через параметр URL (по умолчанию отключено).max_page_size— ограничивает максимальное количество объектов на странице.
Пример использования PageNumberPagination
Давайте настроим наш проект и добавим пагинацию на основе номера страницы.
- Настройка глобальной пагинации
Для начала добавим глобальную настройку пагинации в settings.py. Откройте файл и добавьте следующий параметр:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10, # Количество объектов на одну страницу
}
Теперь каждый ваш API будет возвращать данные, разделённые на страницы.
- Описание маршрута для тестирования
Рассмотрим эндпоинт, который возвращает список объектов. Допустим, у нас есть модель Book с несколькими записями:
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
Создадим представление (APIView) для получения списка книг:
# views.py
from rest_framework.generics import ListAPIView
from .models import Book
from .serializers import BookSerializer
class BookListView(ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
Теперь подключим маршрут:
# urls.py
from django.urls import path
from .views import BookListView
urlpatterns = [
path('books/', BookListView.as_view(), name='book-list'),
]
- Тестирование
PageNumberPagination
С помощью curl или Postman отправьте запрос к эндпоинту /books/:
GET http://localhost:8000/books/
Ответ будет выглядеть примерно так:
{
"count": 50, # Общее количество записей
"next": "http://localhost:8000/books/?page=2", # URL следующей страницы
"previous": null, # Для первой страницы это будет null
"results": [
{ "id": 1, "title": "Книга 1", "author": "Автор 1" },
{ "id": 2, "title": "Книга 2", "author": "Автор 2" },
...
]
}
Если вы добавите параметр ?page=2, то сервер вернет следующую страницу:
GET http://localhost:8000/books/?page=2
LimitOffsetPagination: второй способ пагинации
Теперь давайте перейдём к LimitOffsetPagination. Этот механизм работает немного иначе. Вместо номеров страниц он использует два параметра:
limit— сколько объектов нужно вернуть.offset— количество объектов, которые нужно пропустить (начиная с начала списка).
Этот метод особенно полезен, если вы хотите предоставить пользователю больший контроль над тем, сколько данных будет возвращаться.
Пример использования LimitOffsetPagination
- Настройка глобальной пагинации
Чтобы использовать LimitOffsetPagination, замените настройку в settings.py:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 10, # Лимит по умолчанию
}
- Тестирование
LimitOffsetPagination
Отправим запрос:
GET http://localhost:8000/books/?limit=10&offset=20
Ответ будет содержать 10 объектов, начиная с 21-го:
{
"count": 50, # Общее количество записей
"next": "http://localhost:8000/books/?limit=10&offset=30", # URL следующей страницы
"previous": "http://localhost:8000/books/?limit=10&offset=10", # URL предыдущей страницы
"results": [
{ "id": 21, "title": "Книга 21", "author": "Автор 21" },
{ "id": 22, "title": "Книга 22", "author": "Автор 22" },
...
]
}
Теперь пользователи API могут контролировать, сколько записей они хотят загружать, и откуда начинать.
PageNumberPagination или LimitOffsetPagination?
Если вам нужно просто и интуитивно понятное API для пользователей (где "страница" является основным понятием), то стоит использовать PageNumberPagination. Пользователь просто указывает номер страницы и получает данные.
А вот если для вас важен контроль над количеством данных и гибкость (особенно, если вы работаете с фронтендом, где требуется динамичная подгрузка), — вам подойдёт LimitOffsetPagination.
Дополнительные настройки PageNumberPagination и LimitOffsetPagination
Настройка page_size_query_param
Вы можете дать клиенту возможность управлять размером страницы (page_size) или лимитом (limit). Для этого перейдём к кастомизации пагинации. Создадим кастомный класс:
# pagination.py
from rest_framework.pagination import PageNumberPagination
class CustomPageNumberPagination(PageNumberPagination):
page_size_query_param = 'size' # Теперь клиент может использовать ?size=<число>
max_page_size = 100 # Максимальный размер страницы
Применим этот класс в представлении:
# views.py
from .pagination import CustomPageNumberPagination
class BookListView(ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = CustomPageNumberPagination
Теперь клиент может отправить запрос с параметром ?page=1&size=15 и получить 15 объектов.
Дополнительные параметры в LimitOffsetPagination
Аналогично вы можете кастомизировать LimitOffsetPagination, добавив, например, max_limit, чтобы ограничить максимальное количество возвращаемых объектов.
# pagination.py
from rest_framework.pagination import LimitOffsetPagination
class CustomLimitOffsetPagination(LimitOffsetPagination):
max_limit = 50 # Максимальный лимит
Заключение
Теперь вы знаете, как использовать два самых популярных метода пагинации в DRF. PageNumberPagination и LimitOffsetPagination дают вам возможность не только улучшить отзывчивость API, но и предоставить клиенту нужный объём данных. Выберите тот метод, который отвечает вашим задачам, и начинайте экспериментировать в своём проекте. Увидимся на следующей лекции!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ