Постраничная пагинация в Django

Блог Полезное

Постраничная пагинация в Django

Постраничная пагинация в Django

Что такое пагинация и зачем она нужна вам на сайте? Пагинация в Django есть в стандартных модулях или надо искать сторонние приложения? 

Наверное каждый веб разработчик сталкивался с ситуцией, когда на одной странице сайта выводится много объеков (статей, продуктов, категорий и т.д). Так вот специально для этих целей эти объекты делят на постраничный вывод, например, по 10 статей на странице. Во-первых это удобно для пользователей, во-вторых это не нагружает сервер и браузер выводом большого количества информации на одной странице.

Pagination в Django 

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

 Пагинатор находится в django.contrib.paginator. Чаще всего используются такие объекты как Paginator и Page.

Как использовать

Предположим у нас имеется модель Blog, в которой 100 экземпляров.


class Blog(models.Model):
    title = models.CharField(max_lenght=300)
    slug = models.SlugField()

в views.py:


from .models import Blog
from django.core.paginator import Paginator

list = Blog.objects.all()
paginator = Paginator(list, 10)

List -  это все наши объекты. Импортируем Paginator и разбиваем list на queryset по 10 объектов на страницу. Будут созданы 10 страниц  по 10 объектов (статей) на каждой.

Методы Paginator



paginator.count 100 Число статей
paginator.num_pages 10 Число страниц
paginator.page_range xrange(1, 11) Страниц от и до
paginator.page(3) Page 3 of 10 Текущая страница

Методы Page

blog_list = paginator.page(5)

blog_list	Page 5 of 10	django.core.paginator.Page
blog_list.has_next() True Следующая страница
blog_list.has_previous() True Предыдущая страница
blog_list.has_other_pages() True Другие страницы
blog_list.next_page_number() 3 Номер следующей страницы
blog_list.previous_page_number() 1 Номер предыдущей страницы
blog_list.start_index() 51 С какой статьи начинается страница
blog_list.end_index() 61 Какой заканчивается

Методы blog_list.has_next() и blog_list.has_previous() вызывают исключение InvalidPage, если страниц не существует.

Пагинация в Function-Based View

Напишем предствление. В views.py:


from .models import Blog
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def home(request):
list = Blog.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(blog_list, 10)
try:
blog_list = paginator.page(page)
except PageNotAnInteger:
blog_list = paginator.page(1)
except EmptyPage:
blog_list = paginator.page(paginator.num_pages)
return render(request, 'app/blog_list.html', { 'blog_list': blog_list })

В шаблоне вывода списка статей blog_list.html:



{% for item in blog_list %}
{{ item.title }}
{% endfor %}

{% if blog_list.has_other_pages %}
<ul class="pagination">
{% if blog_list.has_previous %}
<li><a href="?page={{ blog_list.previous_page_number }}">&laquo;</a></li>
{% else %}
<li class="disabled"><span>&laquo;</span></li>
{% endif %}
{% for i in blog_list.paginator.page_range %}
{% if blog_list.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if users.has_next %}
<li><a href="?page={{ blog_list.next_page_number }}">&raquo;</a></li>
{% else %}
<li class="disabled"><span>&raquo;</span></li>
{% endif %}
</ul>
{% endif %}

Пагинация в Class-Based View

С классами немного проще. Не нужно писать в представлении ничего кроме:


class BlogList(ListView):
model = Blog
template_name = 'app/blog_list.html'
paginate_by = 10
queryset = Blog.objects.all()

Как видите мы просто добавили строчку paginate_by и число статей на странице. Теперь посмотрите на небольшие изменения вывода в шаблоне:



{% for item in object_list %}
{{ item.title }}
{% endfor %}

{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li><a href="?page={{ page_obj.previous_page_number }}">&laquo;</a></li>
{% else %}
<li class="disabled"><span>&laquo;</span></li>
{% endif %}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li><a href="?page={{ page_obj.next_page_number }}">&raquo;</a></li>
{% else %}
<li class="disabled"><span>&raquo;</span></li>
{% endif %}
</ul>
{% endif %}

Изменения небольшие, но все же о них стоит помнить. Впринципе это все, что вам надо знать о paginate в Django. Разработка сайтов на фреймворке Django.