Простой блог на Django - часть 9. Внедряем пагинацию в шаблон.

Постов на главной странице может быть бесконечно много, поэтому было бы неплохо сделать пагинацию; для этого мы воспользуемся классом Paginator. Следовательно, пришло время немного модифицировать View функцию: 

paginator = Paginator(latest, paginator_pages)

Ну и сам пагинатор импортируем:

from django.core.paginator import Paginator

Полный код функции:

paginator_pages = 1

def index(request):
  latest = Post.objects.order_by('-pub_date')
  paginator = Paginator(latest, paginator_pages)
  page = paginator.get_page(request.GET.get('page'))
  return render(request, "index.html", {"page": page})

В переменной latest я убрал лимит в 10 записей, потому что за то, сколько страниц будет отображено в итоге, теперь отвечает Paginator. Первым аргументом этому классу передаётся объект запроса типа QuerySet, а вторым - количество элементов, которые будут отображаться на странице (для этого была специально заведена переменная paginator_pages). Поскольку записей у меня немного, чтобы продемонстрировать работу пагинатора, я сделал это значение равным единице. 

Осталось дать пагинатору понять, на какой странице мы находимся и в зависимости от этого отображать разные данные - для этих целей используется метод get_page, которому в качестве аргумента передаётся номер текущей страницы. Ну и в последней строке, в сам шаблон уже передаётся объект Paginator. 

Теперь рассмотрим, как будет происходить работа с объектом пагинации непосредственно в шаблоне. Но для начала, в нём же, поменяем переменную posts на page (так как название переменной поменялось во view функции): 

{% for post in page %}
  {% include "includes/post_in_cat.html" with post=post %}
{% endfor %}

Логика того, как будет отображаться вёрстка для предыдущей, текущей и следующей страницы, прописана в файле paginator.html Внедряем этот файл в шаблон с помощью конструкции include: 

{% include "includes/paginator.html" %}

Основу содержимого этого файла я взял из официальной документации и немного адаптировал под текущую вёрстку. Код paginator.html получился таким:

{% if page.has_other_pages %}
<nav class="nav justify-content-center">
  <ul class="pagination">
    {% if page.has_previous %}
    <li class="page-item">
      <a class="page-link" href="?page={{ page.previous_page_number }}">&laquo; Предыдущая</a>
    </li>
    {% else %}
    <li class="page-item disabled">
      <span class="page-link">&laquo; Предыдущая</span>
    </li>
    {% endif %}
    {% for i in page.paginator.page_range %}
    {% if page.number == i %}
    <li class="page-item active">
      <span class="page-link">{{ i }}
        <span class="sr-only">(текущая)</span>
      </span>
    </li>
    {% else %}
    <li class="page-item">
      <a class="page-link" href="?page={{ i }}">{{ i }}</a>
    </li>
    {% endif %}
    {% endfor %}
    {% if page.has_next %}
    <li class="page-item">
      <a class="page-link" href="?page={{ page.next_page_number }}">Следующая &raquo;</a>
    </li>
    {% else %}
    <li class="page-item disabled">
      <span class="page-link">Следующая &raquo;</span>
    </li>
    {% endif %}
  </ul>
</nav>
{% endif %}

Особо ничего расписывать не буду, потому что, во-первых, это бы заняло слишком много времени, а во-вторых, там и так более-менее всё интуитивно понятно. Теперь если перезагрузить страничку, то увидим результат:

Коммит с изменениями - https://github.com/maclen2007/simple_django_blog/commit/390520692bc21a64434636d44a7c5174d637ce12

Комментарии ()

    Вы должны авторизоваться, чтобы оставлять комментарии.