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  # Максимальний розмір сторінки

Застосуємо цей клас у view:

# 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, але й надати клієнту потрібний обсяг даних. Обери той метод, який відповідає твоїм задачам, і починай експериментувати у своєму проєкті. Побачимось на наступній лекції!

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ