Ответ
Пагинация в Django позволяет разбивать большие наборы данных на отдельные страницы, что улучшает производительность загрузки и удобство использования (UX) для пользователя. Для этого используется встроенный модуль django.core.paginator
.
Основные шаги реализации:
-
Использование
Paginator
во View: В представлении (view) создается экземплярPaginator
, которому передается QuerySet объектов и количество элементов на страницу. Затем извлекается объект страницы (page_obj
) на основе параметра запроса (обычно?page=N
).from django.core.paginator import Paginator from django.shortcuts import render from .models import Post # Предполагается модель Post
def post_list(request): posts = Post.objects.all().order_by('-created_at') # Получаем все посты, сортируем paginator = Paginator(posts, 10) # По 10 постов на страницу
page_number = request.GET.get('page') # Получаем номер текущей страницы из URL
page_obj = paginator.get_page(page_number) # Получаем объект страницы
return render(request, 'blog/post_list.html', {'page_obj': page_obj})
```
Метод `get_page()` безопасно обрабатывает некорректные номера страниц, возвращая первую страницу или последнюю, если номер слишком большой.
-
Отображение пагинации в шаблоне: В шаблоне используется объект
page_obj
для итерации по элементам текущей страницы и для отображения ссылок на другие страницы.<!-- blog/post_list.html --> <h1>Список постов</h1>
{% for post in page_obj %}
{{ post.title }}
{{ post.content|truncatechars:150 }}
{% empty %}
Постов пока нет.
{% endfor %}
```
`page_obj` предоставляет удобные методы и атрибуты, такие как `has_previous`, `has_next`, `previous_page_number`, `next_page_number`, `number` (текущий номер страницы) и `paginator.num_pages` (общее количество страниц).
Пагинация для API (Django REST Framework): Для RESTful API в Django REST Framework (DRF) существуют специализированные классы пагинации, которые возвращают метаданные о пагинации вместе с данными:
PageNumberPagination
: Разбивает данные на страницы по номеру страницы.LimitOffsetPagination
: Позволяет клиенту запрашивать определенное количество элементов, начиная со смещения.CursorPagination
: Использует "курсор" для определения следующей страницы, что эффективно для очень больших наборов данных и предотвращает проблемы с производительностью при изменении данных.
Пример настройки PageNumberPagination
в settings.py
для глобального применения:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
Или для конкретного ViewSet:
# views.py (DRF)
from rest_framework import viewsets
from rest_framework.pagination import PageNumberPagination
from .models import Post
from .serializers import PostSerializer
class StandardResultsSetPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
pagination_class = StandardResultsSetPagination
Выбор метода пагинации зависит от требований к пользовательскому интерфейсу и API.