JavaRush /Курсы /Модуль 3: Django /Настройка базовой пагинации

Настройка базовой пагинации

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

Мы уже дошли до момента, когда наши API начинают становиться умными... ну, почти умными. Сегодня мы будем учиться управлять объемом данных, которые возвращаются клиенту, используя пагинацию. Ведь никто не хочет, чтобы их API возвращал тысячу записей за один запрос: клиенты возненавидят вас за лишний трафик, а сервер — за нагрузку. Итак, сегодня мы настроим базовую пагинацию в Django REST Framework (аббревиатура: DRF).

Почему пагинация так важна?

Программисты любят кофе, но не любят стоять в очереди из 100 человек. Допустим, программист решил пойти отдохнуть (ну, или поработать с ноутбуком) в ближайшую кофейню. Представьте программу, которая отфильтровывает данные о кофейнях для вас. Вы хотите видеть список ближайших 5-10 кофеиновых заведений, а не все на Земле. Аналогично, в API пагинация позволяет вернуть только часть данных — например, первые 10 записей. Клиент может затем запросить следующую партию данных (например, вторую страницу), и так далее.

Вот основные преимущества пагинации в API:

  1. Улучшение производительности. Сервер не перегружается, а клиент получает ответ быстрее.
  2. Экономия трафика. Передается меньше данных за один запрос.
  3. Удобство для пользователя. Информация разбита на страницы, что делает её более доступной.

Итак, пагинация не только снимает нагрузку с сервера, но и делает взаимодействие с вашим API более удобным.

Поддержка пагинации в DRF

Django REST Framework предоставляет несколько готовых классов для работы с пагинацией:

  • PageNumberPagination — пагинация на основе страниц (например, "покажи мне страницу 3, где каждая страница содержит 10 элементов").
  • LimitOffsetPagination — пагинация с указанием смещения (offset) и лимита записей (limit).
  • CursorPagination — пагинация на основе курсора (обычно используется для больших объемов данных).

Сегодня наш фокус на самых популярных вариантах: PageNumberPagination и LimitOffsetPagination. Мы попробуем настроить их на глобальном и локальном уровнях.

Конфигурация пагинации в проекте

Начнем с настройки базовой пагинации в проекте. Для этого нам, как всегда, достаточно немного поколдовать в файле settings.py. DRF позволяет настроить пагинацию глобально, чтобы она автоматически применялась ко всем представлениям, где не предусмотрена кастомная логика.

Давайте добавим базовую пагинацию в settings.py

Для этого открываем файл settings.py нашего проекта и добавляем следующие параметры:

# Настройки REST Framework
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,  # Количество элементов на одной странице
}

Что тут происходит:

  • DEFAULT_PAGINATION_CLASS указывает DRF, какой класс пагинации использовать по умолчанию.
  • PAGE_SIZE — это количество элементов, которые должны возвращаться на одной странице.

Здесь мы настроили так, чтобы клиент получал по 10 записей за один запрос.

Теперь, если вы сделаете запрос к вашему API, он автоматически вернет данные с разделением на страницы.

Как это работает на практике

Для теста нам понадобится представление с выводом данных из модели. Предположим, у нас есть модель Post, представляющая записи блога. Вот как выглядит наш views.py:

from rest_framework.generics import ListAPIView
from .models import Post
from .serializers import PostSerializer

class PostListView(ListAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

Открывая в браузере URL-адрес данного представления или делая GET-запрос через Postman, вы заметите, что данные теперь возвращаются с разделением на страницы.

Пример ответа с первой страницей:

{
    "count": 50,
    "next": "http://127.0.0.1:8000/api/posts/?page=2",
    "previous": null,
    "results": [
        {
            "id": 1,
            "title": "Первая запись",
            "content": "Контент первой записи"
        },
        {
            "id": 2,
            "title": "Вторая запись",
            "content": "Контент второй записи"
        },
        ...
    ]
}

Здесь:

  • count — общее количество объектов.
  • next — ссылка на следующую страницу (если она есть).
  • previous — ссылка на предыдущую страницу (если она есть).
  • results — массив объектов, которые относятся к текущей странице.

Если вы добавите параметр ?page=2 к вашему запросу, вы получите следующий набор записей.

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

Но что, если для разных API-представлений вам нужно установить разные параметры пагинации? DRF позволяет настроить пагинацию не только глобально, но и локально — на уровне представления.

Попробуем переключиться на LimitOffsetPagination в одном конкретном представлении. Вот как это сделать:

from rest_framework.pagination import LimitOffsetPagination
from rest_framework.generics import ListAPIView
from .models import Post
from .serializers import PostSerializer

class CustomLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 5  # Количество объектов по умолчанию
    max_limit = 100    # Максимально допустимое количество объектов

class PostListView(ListAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    pagination_class = CustomLimitOffsetPagination

Теперь наш API будет использовать LimitOffsetPagination. Пользователь может передать параметры limit (количество объектов) и offset (смещение). Пример запроса:

GET /api/posts/?limit=5&offset=10

Ответ API будет выглядеть примерно так:

{
    "count": 50,
    "next": "http://127.0.0.1:8000/api/posts/?limit=5&offset=15",
    "previous": "http://127.0.0.1:8000/api/posts/?limit=5&offset=5",
    "results": [
        {
            "id": 11,
            "title": "Одиннадцатая запись",
            "content": "Контент одиннадцатой записи"
        },
        ...
    ]
}

Здесь параметры next и previous указывают ссылки на соседние "страницы". Это особенно удобно, если у вас есть ленивый скроллинг в пользовательском интерфейсе.

Полезные советы по настройке пагинации

  1. Если вы используете глобальную пагинацию, убедитесь, что она подходит для всех ваших эндпоинтов. Например, размер страницы PAGE_SIZE=10 может быть слишком маленьким или большим для разных API.
  2. Настраивая пагинацию на уровне представления (как в случае с LimitOffsetPagination), попробуйте написать свой кастомный класс, чтобы гибко управлять настройками.
  3. Для больших данных или специфических UI-компонентов (например, карусели с горизонтальной прокруткой) лучше использовать CursorPagination. Но это тема для другой лекции.
1
Задача
Модуль 3: Django, 19 уровень, 1 лекция
Недоступна
Кастомизация пагинации для представления
Кастомизация пагинации для представления
1
Задача
Модуль 3: Django, 19 уровень, 1 лекция
Недоступна
Настройка пагинации с использованием LimitOffsetPagination
Настройка пагинации с использованием LimitOffsetPagination
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ