分页¶ T0>

Django提供了几个类来帮助你管理分页数据 - 也就是说,分成几个页面的数据和“Previous / Next”链接。 这些类位于django/core/paginator.py中。

示例

向Paginator传递一个对象的列表和每页要显示的对象数,返回的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

注意

Note that you can give Paginator a list/tuple, a Django QuerySet, or any other object with a count() or __len__() method. When determining the number of objects contained in the passed object, Paginator will first try calling count(), then fallback to using len() if the passed object has no count() method. 这允许诸如Django的QuerySet的对象在可用时使用更高效的count()方法。

在视图中使用Paginator

下面是一个稍微复杂一点的例子,它使用Paginator来分页查询。 我们同时提供视图和相应的模板,以显示如何显示结果。 这个例子假定你有一个已经被导入的Contacts模型。

视图函数如下所示:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render

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

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

在模板list.html中,您需要在页面之间包含导航以及来自对象本身的任何有趣信息:

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

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

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

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

Paginator 对象

Paginator 类有如下构造器:

Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True)[source]

必需参数

object_list

使用count()__len__()方法的列表,元组,QuerySet或其他可分片对象。 For consistent pagination, QuerySets should be ordered, e.g. with an order_by() clause or with a default ordering on the model.

性能问题分页大型的QuerySet s

If you’re using a QuerySet with a very large number of items, requesting high page numbers might be slow on some databases, because the resulting LIMIT/OFFSET query needs to count the number of OFFSET records which takes longer as the page number gets higher.

per_page
不包括孤儿的项目的最大数量(参见下面的orphans可选参数)。

可选参数

orphans
当你不想有一个项目很少的最后一页时使用这个。 如果最后一页通常有少于或等于orphans的项目,那么这些项目将被添加到上一页(这成为最后一页)而不是将项目留在页面上通过他们自己。 例如,对于23个项目,per_page=10orphans=3,将会有两个页面;带有10个项目的第一页和带有13个项目的第二个(和最后一个)页面。 orphans默认为零,这意味着网页从不合并,最后一页可能有一个项目。
allow_empty_first_page
是否允许第一页为空。 如果Falseobject_list为空,则会引发EmptyPage错误。

方法¶ T0>

Paginator.get_page(number)[source]
Django 2.0新增功能

使用给定的基于1的索引返回一个Page对象,同时处理超出范围和无效的页码。

如果页面不是数字,则返回第一页。 如果页码为负数或大于页数,则返回最后一页。

只有在指定Paginator(..., allow_empty_first_page = False)时,才会引发异常(EmptyPage object_list是空的。

分页程序。page(number)[source]

使用给定的基于1的索引返回一个Page对象。 如果给定页码不存在,则引发InvalidPage

属性¶ T0>

分页程序。计数 T0> ¶ T1>

所有页面上的对象总数。

注意

当确定包含在object_list中的对象的数量时,Paginator将首先调用object_list.count() If object_list has no count() method, then Paginator will fallback to using len(object_list). 这允许诸如Django的QuerySet的对象在可用时使用更高效的count()方法。

Paginator.num_pages

总页数。

Paginator.page_range

A 1-based range iterator of page numbers, e.g. yielding [1, 2, 3, 4].

InvalidPage异常

例外 InvalidPage[source]

paginator传递无效页码时引发异常的基类。

如果请求的页面无效(即不是整数)或者不包含对象,则Paginator.page()方法会引发异常。 通常,捕获InvalidPage异常就足够了,但是如果您希望获得更多的粒度,则可以捕获以下任一异常:

例外 PageNotAnInteger[source]

page()被赋予一个不是整数的值时引发。

例外 EmptyPage[source]

page()被赋予一个有效的值,但在那个页面上不存在对象时引发。

Both of the exceptions are subclasses of InvalidPage, so you can handle them both with a simple except InvalidPage.

Page对象

您通常不会手动构建Page对象 - 您可以使用Paginator.page()获取它们。

Pageobject_listnumberpaginator[source] T6>

当使用len()或直接迭代它时,页面就像Page.object_list的序列。

方法¶ T0>

Page.has_next()[source]

如果有下一页,则返回True

Page.has_previous()[source]

如果有前一页,则返回True

Page.has_other_pages()[source]

如果存在下一个前一页,则返回True

Page.next_page_number()[source]

返回下一个页码。 如果下一页不存在,则引发InvalidPage

Page.previous_page_number()[source]

返回上一页的页码。 如果前一页不存在,则引发InvalidPage

Page.start_index()[source]

相对于分页程序列表中的所有对象,返回页面上第一个对象的从1开始的索引。 例如,当为每页2个对象分页列出5个对象时,第二页的start_index()将返回3

Page.end_index()[source]

相对于分页程序列表中的所有对象,返回页面上最后一个对象的从1开始的索引。 例如,当为每页2个对象分页列出5个对象时,第二页的end_index()将返回4

属性¶ T0>

Page.object_list

此页面上的对象列表。

Page.number

此页面的基于1的页码。

Page.paginator

关联的Paginator对象。