Пагинация

Django предоставляет методы высокого и низкого уровня, которые помогают разбивать данные на страницы, то есть данные, которые разделены на несколько страниц, с помощью ссылок «Предыдущий / Следующий».

Класс Paginator

Под капотом все методы разбиения на страницы используют этот класс Paginator . Он выполняет всю работу по разделению объекта QuerySet на объекты Page .

Пример

Предоставляя Paginator список объектов вместе с количеством элементов, которые вы хотите на каждой странице, этот класс предоставляет вам методы для доступа к элементам на разных страницах:

>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2)

>>> p.count
4
>>> p.num_pages
2
>>> type(p.page_range)
<class 'range_iterator'>
>>> p.page_range
range(1, 3)

>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']

>>> page2 = p.page(2)
>>> page2.object_list
['george', 'ringo']
>>> page2.has_next()
False
>>> page2.has_previous()
True
>>> page2.has_other_pages()
True
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number()
1
>>> page2.start_index() # The 1-based index of the first item on this page
3
>>> page2.end_index() # The 1-based index of the last item on this page
4

>>> p.page(0)
Traceback (most recent call last):
...
EmptyPage: That page number is less than 1
>>> p.page(3)
Traceback (most recent call last):
...
EmptyPage: That page contains no results

Заметка

Обратите внимание, что вы можете Paginator указать список / кортеж, QuerySet Django или любой другой объект, у которого есть метод count() или __len__() . Чтобы определить количество объектов, содержащихся в переданном объекте, Paginator сначала попробуйте позвонить count() и вернуться, len() если у рассматриваемого объекта нет метода count() . Это позволяет таким объектам, как QuerySet Django, использовать count() более эффективный метод там, где это необходимо.

Пагинация вида ListView

django.views.generic.list.ListView предлагает встроенную возможность разбивать список на страницы для отображения. Это делается путем добавления атрибута paginate_by к классу представления, например

from django.views.generic import ListView

from myapp.models import Contact

class ContactList(ListView):
    paginate_by = 2
    model = Contact

Это ограничивает количество объектов на странице и добавляет переменные paginator и page_obj контекст. Чтобы пользователи могли перемещаться между страницами, добавьте в шаблон ссылки на следующую и предыдущую страницы, например:

{% for contact in page_obj %}
    {# Each "contact" is a Contact model object. #}
    {{ contact.full_name|upper }}<br>
    ...
{% endfor %}

<div class="pagination">
    <span class="step-links">
        {% if page_obj.has_previous %}
            <a href="?page=1">&laquo; first</a>
            <a href="?page={{ page_obj.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
        </span>

        {% if page_obj.has_next %}
            <a href="?page={{ page_obj.next_page_number }}">next</a>
            <a href="?page={{ page_obj.paginator.num_pages }}">last &raquo;</a>
        {% endif %}
    </span>
</div>

Использование Paginator в функции просмотра

Вот пример использования Paginator функции просмотра для разбивки запроса на страницы.

from django.core.paginator import Paginator
from django.shortcuts import render

from myapp.models import Contact

def listing(request):
    contact_list = Contact.objects.all()
    paginator = Paginator(contact_list, 25) # Show 25 contacts per page.

    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    return render(request, 'list.html', {'page_obj': page_obj})

В набор элементов list.html можно включить навигационные ссылки между страницами так же, как в набор элементов в представлении ListView выше.

Copyright ©2020 All rights reserved