Django
December 31, 2023

Удобная Пагинация в Django

Пагинация — это распространенная практика веб-разработки, используемая для разделения больших наборов данных на меньшие и более управляемые части, отображаемые на нескольких страницах.

Рассмотрим один из удачных примеров постраничной пагинации в Django, используя класс Paginator. Такая пагинация удобна для пользователя и обычно подходит для большинства случаев.

Интерфейс пагинатора

Этот вид пагинации позволяет:

  • перемещаться на следующую и предыдущую страницы с помощью кнопок Prev и Next;
  • перемещаться на первую и последнюю страницы с любой страницы;
  • перемещаться через одну страницу.

Пагинация в Django

Вы можете ознакомиться с подробной информацией о пагинации в Django по следующим ссылкам:

Кратко напомню, что пагинация в Django осуществляется с помощью классов Paginator и Page. Paginator разбивает большой набор данных на страницы и принимает в качестве параметров набор объектов (list, tuple или QuerySet) и размер страницы. Page представляет текущую страницу в пагинации и содержит объекты страницы и информацию о соседних страницах.

Пагинатор можно создавать вручную или автоматически с использованием Class-Based Views. В шаблон передается объект страницы (page_obj), который содержит объекты, информацию о страницах и сам пагинатор.

Используемые атрибуты страницы в рассматриваемой пагинации:

  • page_obj.has_previous: проверяет, есть ли предыдущая страница.
  • page_obj.has_next: проверяет, есть ли следующая страница.
  • page_obj.previous_page_number: возвращает номер предыдущей страницы.
  • page_obj.next_page_number: возвращает номер следующей страницы.
  • page_obj.number: возвращает номер текущей страницы.
  • page_obj.paginator: возвращает экземпляр класса Paginator.
  • page_obj.paginator.num_pages: возвращает общее количество страниц.
  • page_obj.paginator.page_range: возвращает диапазон страниц.

Также в рассматриваемой пагинации используется фильтр шаблонов add, который позволяет прибавлять значения к переменным прямо в шаблоне.

User-Fiendly пагианция

На скриншоте показано как будет выглядеть пагинатор на различных страницах. Пагинатор всегда отображает крайние страницы и две соседние страницы, если они существуют. Также отображаются кнопки Prev и Next, если текущая страница не является крайней.

Пагинатор на разных страницах

В следующем листинге представлена реализация этой пагинации. Просто вставьте этот код в свой проект, и скорее всего, все должно работать. Далее мы рассмотрим этот листинг подробнее.

{% if page_obj.has_previous %}
  <li><a href="?page={{ page_obj.previous_page_number }}">(Prev)</a></li>

  {% if page_obj.number > 3 %}
      <li><a href="?page=1">(1)</a></li>
    {% if page_obj.number > 4 %}
      <li><a >...</a></li>
    {% endif %}
  {% endif %}
{% endif %}

{% for num in page_obj.paginator.page_range %}
  {% if page_obj.number == num %}
      <li><a href="?page={{ num }}">({{ num }})</a></li>
  {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
      <li><a href="?page={{ num }}">({{ num }})</a></li>
  {% endif %}
{% endfor %}

{% if page_obj.has_next %}
  {% if page_obj.number < page_obj.paginator.num_pages|add:'-3' %}
    <li><a >...</a></li>
    <li><a href="?page={{ page_obj.paginator.num_pages }}">
      ({{ page_obj.paginator.num_pages }})
    </a></li>
  {% elif page_obj.number < page_obj.paginator.num_pages|add:'-2' %}
    <li><a href="?page={{ page_obj.paginator.num_pages }}">
      ({{ page_obj.paginator.num_pages }})
    </a></li>
  {% endif %}

  <li><a href="?page={{ page_obj.next_page_number }}">(Next)</a></li>
{% endif %}

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

1. Ссылка на Предыдущую Страницу:

{% if page_obj.has_previous %}
  <li><a href="?page={{ page_obj.previous_page_number }}">(Prev)</a></li>

Если page_obj.has_previous равно True, он показывает кнопку Prev на предыдущую страницу. Переменная page_obj.previous_page_number содержит номер предыдущей страницы.

2. Ссылки на Первые Страницы и Многоточие:

{% if page_obj.number > 3 %}
    <li><a href="?page=1">(1)</a></li>
  {% if page_obj.number > 4 %}
    <li><a >...</a></li>
  {% endif %}
{% endif %}

Эти строки кода обрабатывают отображение ссылки на первую страницу и многоточие (...), если текущий номер страницы больше 3 (или 4 для многоточия).

3. Текущая Страница и Ссылки на Соседние Страницы:

{% for num in page_obj.paginator.page_range %}
  {% if page_obj.number == num %}
      <li><a href="?page={{ num }}">({{ num }})</a></li>
  {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
      <li><a href="?page={{ num }}">({{ num }})</a></li>
  {% endif %}
{% endfor %}

Этот цикл проходит через диапазон страниц в пагинаторе. Он проверяет два условия:

  • Если номер страницы (num) является текущей страницей (page_obj.number), он создает для нее ссылку. Обычно это оформляется по-разному, чтобы указать на текущую страницу.
  • Если номер страницы находится в пределах трех страниц до или после текущей страницы, он также создает ссылки на эти страницы. Таким образом, пользователь может переходить к ближайшим двум страницам, не просматривая весь диапазон.

4. Многоточие и Ссылка на Последнюю Страницу:

{% if page_obj.has_next %}
{% if page_obj.number < page_obj.paginator.num_pages|add:'-3' %}
<li><a >...</a></li>
<li><a href="?page={{ page_obj.paginator.num_pages }}">
  ({{ page_obj.paginator.num_pages }})
</a></li>
{% elif page_obj.number < page_obj.paginator.num_pages|add:'-2' %}
<li><a href="?page={{ page_obj.paginator.num_pages }}">
  ({{ page_obj.paginator.num_pages }})
</a></li>
{% endif %}

Эта часть похожа на второй раздел, но для конца диапазона пагинации. Она отображает многоточие и ссылку на последнюю страницу, если текущая страница находится на нескольких страницах от последней.

5. Ссылка на Следующую Страницу:

{% if page_obj.has_next %}
...  
<li><a href="?page={{ page_obj.next_page_number }}">(Next)</a></li>
{% endif %}

Аналогично первой части, только кнопка для перехода на следующую страницу.


Заключение

Мы рассмотрели пример простой и интуитивно понятной постраничной пагинации в Django, которая позволяет пользователям легко перемещаться по страницам и получать нужную информацию.

Реализация пагинации может быть адаптирована под ваши потребности, и вы можете внести изменения в код, чтобы соответствовать требованиям вашего проекта. Удачи в использовании пагинации в ваших Django приложениях!