Пагинация

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указать список / кортеж, Django QuerySetили любой другой объект с помощью метода count()или __len__(). При определении количества объектов, содержащихся в переданном объекте, Paginatorсначала будет попытаться вызвать count(), а затем вернуться к использованию, len()если переданный объект не имеет count()метода. Это позволяет таким объектам, как Django, QuerySetиспользовать более эффективный count() метод, когда он доступен.

Пагинация ListView

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

from django.views.generic import ListView

from myapp.models import Contact

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

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

{% 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 ©2021 All rights reserved