Для этого первым делом создадим шаблон templates/pagination.html, и добавим в него следующий код:
{% if is_paginated %}
<div class="pagination p-3">
{% for page_number in page_obj.paginator.get_elided_page_range %}
{% if page_number == page_obj.paginator.ELLIPSIS %}
{{page_number}}
{% else %}
<a href="?page={{ page_number }}" class="page-link">
{{page_number}}
</a>
{% endif %}
{% endfor %}
</div>
{%endif%}
Давайте разберем его, через условие {% if is_paginated %} мы проверяем активна ли пагинация, чтобы не показывать ничего, когда количество записей меньше чем, указано в представлении.
Далее мы запускаем цикл через метод paginator.get_elided_page_range, он возвращает список номеров страниц, похожий на paginator.page_range, но может добавить многоточие к одной или обеим сторонам текущего номера страницы, когда Paginator.num_pages большой.
Paginator.get_elided_page_range(число, *, on_each_side=3, on_ends=2)
Количество страниц, которые нужно включить с каждой стороны текущего номера страницы, определяется аргументом on_each_side, который по умолчанию равен 3.
Количество страниц, которые нужно включить в начале и конце диапазона страниц, определяется аргументом on_ends, который по умолчанию равен 2.
Например, с значениями по умолчанию для on_each_side и on_ends, если текущая страница 10 и есть 50 страниц, диапазон страниц будет [1, 2, '...', 7, 8, 9, 10, 11, 12, 13, '...', 49, 50].
Это приведет к страницам 7, 8 и 9 слева от и 11, 12 и 13 справа от текущей страницы, а также страницы 1 и 2 в начале и 49 и 50 в конце.
Далее мы проверяем на совпадение номера страницы с paginator.ELLIPSIS, это строка, используемая в качестве замены выброшенных номеров страниц в диапазоне страниц, возвращенном get_elided_page_range(). По умолчанию это '…'. И если она не равна, то выводим номера страниц как ссылки.
И подключим данный файл в main.html:
# остальной шаблон
<div class="col-lg-8 p-4">
{% block content %}
{% endblock %}
{% include 'pagination.html' %}
</div>
# остальной шаблон
Осталось доработать наши представления, для этого в класс PostListView, который мы используем для главной странице и добавим ему параметр paginate_by = 2:
class PostListView(ListView):
model = Post
template_name = 'blog/post_list.html'
context_object_name = 'posts'
paginate_by = 2
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Главная страница'
return context
Также мы можем добавить эту переменную в класс вывода записей в категориях, для этого в PostFromCategory добавим:
class PostFromCategory(ListView):
model = Post
template_name = 'blog/post_list.html'
context_object_name = 'posts'
category = None
paginate_by = 1
# остальные методы класса
На главной странице мы установили ограничение в 2 записи на странице, а в выводе записей в категориях мы установили ограничение в 1 запись. Конечно эти ограничения далеки от тех, которые необходимо использовать на сайте, но так мы можем протестировать работу пагинации.
Запустим сервер и перейдем на главную страницу:
Мы видим нашу пагинацию внизу страницы.
Перейдем в категории и мы увидим что она у нас прекрасно работает. А в случае если будет всего 1 запись на странице, кнопок с номерами страниц не будет.
На этом разработка пагинации закончена.