Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Пагинация
pagination

Пагинация

Стили пагинации, кастомная пагинация, настройка вывода

Пагинация в Django REST Framework

Пагинация разбивает большие наборы данных на страницы. DRF предоставляет несколько стилей пагинации и позволяет создавать кастомные.

#Настройка пагинации

Глобальная настройка в settings.py:

REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 20, # Количество записей на странице по умолчанию }

#PageNumberPagination

Пагинация по номеру страницы через параметр ?page=:

from rest_framework.pagination import PageNumberPagination class ArticleList(generics.ListAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = PageNumberPagination

Запросы:

  • GET /articles/?page=1 — первая страница
  • GET /articles/?page=2 — вторая страница

Ответ:

{ "count": 150, "next": "http://example.com/articles/?page=2", "previous": null, "results": [ {...}, {...} ] }

#Кастомизация PageNumberPagination

from rest_framework.pagination import PageNumberPagination class CustomPageNumberPagination(PageNumberPagination): page_size = 20 # Записей на странице по умолчанию page_size_query_param = 'page_size' # Параметр для изменения размера max_page_size = 100 # Максимальный размер страницы page_query_param = 'page' # Параметр номера страницы # views.py class ArticleList(generics.ListAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = CustomPageNumberPagination

Запросы:

  • GET /articles/?page=2&page_size=50 — страница 2, по 50 записей

#LimitOffsetPagination

Пагинация через лимит и смещение:

from rest_framework.pagination import LimitOffsetPagination class ArticleList(generics.ListAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = LimitOffsetPagination

Параметры:

  • limit — количество записей
  • offset — смещение от начала

Запросы:

  • GET /articles/?limit=20&offset=0 — первые 20
  • GET /articles/?limit=20&offset=20 — следующие 20 (страница 2)
  • GET /articles/?limit=10&offset=50 — 10 записей, начиная с 51-й

Ответ:

{ "count": 150, "next": "http://example.com/articles/?limit=20&offset=20", "previous": null, "results": [...] }

#Кастомизация LimitOffsetPagination

class CustomLimitOffsetPagination(LimitOffsetPagination): default_limit = 20 # Записей по умолчанию limit_query_param = 'limit' offset_query_param = 'offset' max_limit = 100 # Максимальный лимит

#CursorPagination

Пагинация на основе курсора — указателя на позицию:

from rest_framework.pagination import CursorPagination class CreatedCursorPagination(CursorPagination): ordering = '-created_at' # Обязательное поле page_size = 20 page_size_query_param = 'page_size' max_page_size = 100 # views.py class ArticleList(generics.ListAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = CreatedCursorPagination

Запросы:

  • GET /articles/?cursor=cD0yMDI0LTAxLTAx — следующая страница

Ответ:

{ "next": "http://example.com/articles/?cursor=cD0yMDI0LTAxLTAx", "previous": null, "results": [...] }

Преимущества CursorPagination:

  • Стабильность при изменении данных (добавление/удаление не ломает пагинацию)
  • Подходит для больших наборов данных
  • Невозможно «перепрыгнуть» на произвольную страницу (только next/previous)

Недостатки:

  • Нельзя перейти на конкретную страницу (только последовательно)
  • Требует поля для сортировки (ordering)

#Отключение пагинации

#Для конкретного view

class ArticleList(generics.ListAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = None # Отключить пагинацию

#Глобальное отключение

REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': None, }

#Кастомная пагинация

Создание своего класса пагинации:

from rest_framework.pagination import PageNumberPagination from rest_framework.response import Response class CustomPagination(PageNumberPagination): page_size = 20 page_size_query_param = 'size' max_page_size = 100 def get_paginated_response(self, data): """Кастомный формат ответа""" return Response({ 'meta': { 'total': self.page.paginator.count, 'page': self.page.number, 'per_page': self.page_size, 'total_pages': self.page.paginator.num_pages, 'has_next': self.page.has_next(), 'has_prev': self.page.has_previous(), }, 'data': data })

Ответ:

{ "meta": { "total": 150, "page": 2, "per_page": 20, "total_pages": 8, "has_next": true, "has_prev": true }, "data": [...] }

#Пагинация с деталями

Более подробный ответ с информацией о странице:

from rest_framework.pagination import PageNumberPagination from rest_framework.response import Response from collections import OrderedDict class DetailedPagination(PageNumberPagination): page_size = 20 page_size_query_param = 'size' max_page_size = 100 def get_paginated_response(self, data): return Response(OrderedDict([ ('count', self.page.paginator.count), ('next', self.get_next_link()), ('previous', self.get_previous_link()), ('results', data), ('page', self.page.number), ('page_size', self.page_size), ('total_pages', self.page.paginator.num_pages), ]))

#Пагинация в ViewSet

from rest_framework import viewsets from rest_framework.pagination import PageNumberPagination class ArticlePagination(PageNumberPagination): page_size = 20 page_size_query_param = 'size' max_page_size = 100 class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = ArticlePagination

#Выбор пагинации в зависимости от запроса

class FlexiblePagination(PageNumberPagination): def __init__(self): super().__init__() self.page_size = 20 def get_page_size(self, request): """Динамический размер страницы""" if request.query_params.get('full'): return None # Без пагинации return super().get_page_size(request) class ArticleList(generics.ListAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = FlexiblePagination

Запрос:

  • GET /articles/ — с пагинацией (20 записей)
  • GET /articles/?full=true — без пагинации (все записи)

#Сравнение стилей пагинации

СтильПараметрыПлюсыМинусыКогда использовать
PageNumber?page=Простота, понятностьНестабильность при изменении данныхБлоги, каталоги
LimitOffset?limit=&offset=Гибкость, произвольный доступМедленно на больших offsetАдминки, таблицы
Cursor?cursor=Стабильность, производительностьНет произвольного доступаЛенты, чаты, большие данные

#Best Practices

  1. Всегда используйте пагинацию для списков — не возвращайте все записи
  2. PAGE_SIZE по умолчанию — 20-50 записей
  3. max_page_size — ограничьте максимальный размер страницы (100-200)
  4. CursorPagination для лент — стабильность при добавлении новых записей
  5. Индексируйте поля сортировки — особенно для CursorPagination
  6. Документируйте пагинацию — укажите параметры в API docs

Далее: Версионирование API