JavaRush /Курсы /Модуль 3: Django /Пагинация с PageNumberPagination и LimitOffsetPagination ...

Пагинация с PageNumberPagination и LimitOffsetPagination в Django REST Framework

Модуль 3: Django
19 уровень , 2 лекция
Открыта

Добро пожаловать на очередное погружение в мир 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

Давайте настроим наш проект и добавим пагинацию на основе номера страницы.

  1. Настройка глобальной пагинации

Для начала добавим глобальную настройку пагинации в settings.py. Откройте файл и добавьте следующий параметр:

# settings.py

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,  # Количество объектов на одну страницу
}

Теперь каждый ваш API будет возвращать данные, разделённые на страницы.

  1. Описание маршрута для тестирования

Рассмотрим эндпоинт, который возвращает список объектов. Допустим, у нас есть модель 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'),
]
  1. Тестирование 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

  1. Настройка глобальной пагинации

Чтобы использовать LimitOffsetPagination, замените настройку в settings.py:

# settings.py

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10,  # Лимит по умолчанию
}
  1. Тестирование 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, но и предоставить клиенту нужный объём данных. Выберите тот метод, который отвечает вашим задачам, и начинайте экспериментировать в своём проекте. Увидимся на следующей лекции!

1
Задача
Модуль 3: Django, 19 уровень, 2 лекция
Недоступна
Простейшая реализация PageNumberPagination
Простейшая реализация PageNumberPagination
1
Задача
Модуль 3: Django, 19 уровень, 2 лекция
Недоступна
Кастомизация LimitOffsetPagination
Кастомизация LimitOffsetPagination
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ