Блог на Django #17: Добавление пагинации

Добавляя контент на блог, вы быстро придете к выводу, что список постов лучше делить на несколько страниц. В Django есть встроенный класс пагинации, который позволяет сделать это очень быстро.

Отредактируйте файл views.py приложения blog, чтобы импортировать класс Paginator и измените представление post_list следующим образом:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger  
  
  
def post_list(request):  
    object_list = Post.published.all()  
    paginator = Paginator(object_list, 3)  # 3 поста на каждой странице  
    page = request.GET.get('page')  
    try:  
        posts = paginator.page(page)  
    except PageNotAnInteger:  
        # Если страница не является целым числом, поставим первую страницу  
        posts = paginator.page(1)  
    except EmptyPage:  
        # Если страница больше максимальной, доставить последнюю страницу результатов  
        posts = paginator.page(paginator.num_pages)  
    return render(request,  
	          'blog/post/list.html',  
		  {'page': page,  
		   'posts': posts})

Вот как работает этот класс:

  1. Создается экземпляр класса Paginator с количеством объектов, которые нужно отображать на одной странице.
  2. Получаем параметр page GET, который указывает на текущую страницу.
  3. Получаем объекты для нужной страницы, вызывая метод page() метода Paginator.
  4. Если параметр page — это не целое число, возвращаем первую страницу результатов. Если оно больше последней страницы результатов, возвращаем последнюю.
  5. Передаем шаблону номер страницы и полученные объекты.

Теперь нужно создать шаблон для отображения пагинатора так, чтобы он мог использоваться в любом шаблоне с пагинацией. В папке templates/ приложения blog создайте новый файл и назовите его pagination.html. Добавьте туда следующий код:

<div class="pagination">  
 <span class="step-links">  
  {% if page.has_previous %}  
      <a href="?page={{ page.previous_page_number }}">Previous</a>  
  {% endif %}  
    <span class="current">  
  Page {{ page.number }} of {{ page.paginator.num_pages }}.  
    </span>  
  {% if page.has_next %}  
        <a href="?page={{ page.next_page_number }}">Next</a>  
  {% endif %}  
  </span>  
</div>

Шаблон пагинации ожидает получить объект Page, чтобы отрисовать ссылки «Previous» и «Next», а также для отображения текущей страницы и общее количество страниц результата. Вернемся к шаблону blog/post/list.html и добавим шаблон pagination.html в нижней части блока {% content %}:

{% block content %} 
  ... 
  {% include "../pagination.html" with page=posts %} 
{% endblock %}

Поскольку объект Page, который передается шаблону, называется posts, передадим шаблон пагинации в шаблон списка постов вместе с параметрами для корректного рендеринга. Этот способ можно применять, чтобы использовать шаблон пагинации в постраничных представлениях разных моделей.

Теперь откройте https://127.0.0.1:8000/blog/ в браузере. Вы увидите элементы навигации по страницам в нижней части и сможете перемещаться по ним.

Элементы навигации по страницам django