JavaRush /Курси /Модуль 3: Django /Пагінація даних

Пагінація даних

Модуль 3: Django
Рівень 8 , Лекція 8
Відкрита

Припустимо, ми на тій стадії, коли в базі даних нашого Django-додатку накопичилося стільки записів, що їх неможливо "з'їсти" за один раз. Давайте вивчимо пагінацію — інструмент, який допомагає розрізати дані на зручні порції. Готові? Починаємо!

Навіщо потрібна пагінація?

Уявіть собі гіпотетичний інтернет-магазин з мільйонами товарів. Якщо ви раптом вирішите вивести всі ці товари на одну веб-сторінку, то ваш сервер може попрощатися з адекватною продуктивністю, а ваш користувач — зі стабільним інтернет-з'єднанням. Це не опис кінця світу, але вже близько.

Пагінація дозволяє розбити величезні масиви даних (наприклад, записи QuerySet) на сторінки фіксованого розміру і надавати їх користувачеві порціями. Це корисно для відображення даних у таблицях, списках, стрічках соцмереж або будь-яких інших інтерфейсах, де обсяг інформації потенційно великий.

Ось ще пара причин освоїти пагінацію:

  • Користувацький досвід: ніхто не хоче прокручувати нескінченну сторінку.
  • Зменшення навантаження на сервер: менше переданих даних.
  • Прискорення відображення даних: користувачі швидше отримують інформацію (маленькими шматочками).

Давайте одразу перейдемо до практики. Погнали!

Реалізація пагінації в Django

Django надає вбудовані інструменти для пагінації, які легко інтегруються з вашими представленнями та QuerySet. Основний герой тут — клас Paginator, про який ми поговоримо нижче.

1. Клас Paginator

Клас Paginator із модуля django.core.paginator бере QuerySet або список даних і "ріже" його на сторінки. Кожна сторінка представляє собою набір записів, з якими можна працювати.

Приклад використання Paginator

Почнемо з простого прикладу та створимо пагінатор. Припустимо, ми хочемо розбити список продуктів на порції по 10 штук:

from django.core.paginator import Paginator

# Список даних (наприклад, товари в інтернет-магазині)
products = ['Товар 1', 'Товар 2', 'Товар 3', 'Товар 4', 'Товар 5',
            'Товар 6', 'Товар 7', 'Товар 8', 'Товар 9', 'Товар 10',
            'Товар 11', 'Товар 12']

# Створюємо пагінатор з розміром сторінки = 5
paginator = Paginator(products, 5)

# Доступ до сторінок
page_1 = paginator.page(1)  # Перша сторінка
page_2 = paginator.page(2)  # Друга сторінка

# Виводимо дані на сторінці 1
print(page_1.object_list)  # ['Товар 1', 'Товар 2', 'Товар 3', 'Товар 4', 'Товар 5']

# Перевіряємо, чи є наступна сторінка
print(page_1.has_next())  # True
print(page_2.has_next())  # False

# Загальна інформація про пагінацію
print(paginator.count)  # Загальна кількість об'єктів (12)
print(paginator.num_pages)  # Загальна кількість сторінок (3)
print(page_1.number)  # Номер поточної сторінки (1)

Важливі методи об'єкта Paginator:

  • count: загальна кількість об'єктів.
  • num_pages: кількість сторінок.
  • page(number): отримання об'єкта сторінки за номером.
  • has_next() і has_previous(): перевірка наявності наступної або попередньої сторінки.

2. Пагінація у представленнях

Тепер ми готові інтегрувати пагінацію в додаток Django. Додамо пагінацію для списку об'єктів у нашому представленні.

Приклад інтеграції пагінації у представленні

Нехай у нас є модель Product:

# models.py
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    def __str__(self):
        return self.name

Додамо представлення для відображення продуктів із пагінацією:

# views.py
from django.core.paginator import Paginator
from django.shortcuts import render
from .models import Product

def product_list_view(request):
    products = Product.objects.all()
    paginator = Paginator(products, 10)  # Показувати по 10 записів на сторінці

    page_number = request.GET.get('page')  # Отримуємо номер сторінки із запиту
    page_obj = paginator.get_page(page_number)  # Отримуємо поточну сторінку

    return render(request, 'product_list.html', {'page_obj': page_obj})

На що тут звернути увагу:

  • request.GET.get('page') — номер поточної сторінки передається через GET-параметр.
  • paginator.get_page() — повертає об'єкт сторінки, навіть якщо номер сторінки відсутній або некоректний.

Шаблон для відображення

Тепер давайте додамо HTML-шаблон, який буде відображати дані з пагінацією:

<!-- templates/product_list.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Список продуктів</title>
</head>
<body>
    <h1>Список продуктів</h1>
    <ul>
        {% for product in page_obj %}
            <li>{{ product.name }} - {{ product.price }} грн.</li>
        {% endfor %}
    </ul>

    <!-- Пагінація -->
    <div>
        {% if page_obj.has_previous %}
            <a href="?page={{ page_obj.previous_page_number }}">Попередня</a>
        {% endif %}

        <span>Сторінка {{ page_obj.number }} із {{ page_obj.paginator.num_pages }}</span>

        {% if page_obj.has_next %}
            <a href="?page={{ page_obj.next_page_number }}">Наступна</a>
        {% endif %}
    </div>
</body>
</html>

Цей шаблон виводить список продуктів, а нижче — елементи керування для переходу між сторінками.

3. Покращення користувацького досвіду

Пагінація працює, але давайте трохи наблизимо її до реальності. У реальних додатках користувачі очікують бачити номери сторінок, щоб одразу перейти до потрібної.

<div>
    {% for num in page_obj.paginator.page_range %}
        {% if num == page_obj.number %}
            <strong>{{ num }}</strong> <!-- Поточна сторінка -->
        {% else %}
            <a href="?page={{ num }}">{{ num }}</a>
        {% endif %}
    {% endfor %}
</div>

Тепер користувачі зможуть побачити номери всіх сторінок і легко перемикатися між ними.

Практичне завдання

  1. Створіть новий Django-додаток для управління студентами. Назвіть модель Student.
  2. Додайте атрибути first_name, last_name та grade (середній бал).
  3. Заповніть базу даних тестовими даними (наприклад, 50 студентів).
  4. Налаштуйте представлення та шаблон для відображення студентів по 10 записів на сторінці.
  5. Реалізуйте пагінацію з відображенням номерів сторінок.

Ваш додаток має показувати список студентів із кнопками "Попередня", "Наступна" та номерами сторінок (наприклад, 1, 2, 3).

Порада:

пагінація часто трапляється у реальному житті! Якщо ви впораєтесь із цим завданням, вас уже не злякає список із мільйона котиків (або студентів), який потрібно розбити на сторінки. І не забудьте протестувати пагінацію з порожнім QuerySet — там теж можуть бути сюрпризи!

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