Django专门提供了一个paginator模块,实现分页很easy。下面的例子引用了django官方文档:https://docs.djangoproject.com/en/1.11/topics/pagination/
Paginator实例化需要2个参数,一个是待分页的对象list(需要实现count方法或者__len__方法),另一个是每页数量。
Paginator对象属性:
count 对象数量
num_pages 总页数
page_range 所有页数范围的生成器
>>> 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)
>>> p.page_range
range(1, 3)
Paginator对象的重要方法,page(),接受一个页码作为参数,返回一个当前页对象。该对象的几个属性和方法:
object_list 当前页的对象列表
has_next() 有无下一页
has_ previous() 有无上一页
has_other_pages() 有无其他页
next_page_number() 下一页页码
previous_page_number() 上一页页码
start_index() 返回当前页第一个对象的在所有对象中的索引,注意,从1开始
end_index() 返回当前页最后一个对象在所有对象中的索引,注意,从1开始
paginator 所关联的Paginator对象
>>> page1 = p.page(1)
>>> page1
>>> 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
Pagenator的page方法,若传给一个无页码范围之外都值,则得到一个EmptyPage的异常。
>>> 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
在视图中可以这么用:
# views.py
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) # 每页显示25个
page = request.GET.get('page') # 拿到页码参数
try:
contacts = paginator.page(page)
except PageNotAnInteger:
# 捕获到页码不是整数,返回第一页
contacts = paginator.page(1)
except EmptyPage:
# 页码超出范围,返回最后一页
contacts = paginator.page(paginator.num_pages)
return render(request, 'list.html', {'contacts': contacts})
contacts对象是用带有分页信息的QuerySet,用来渲染模板:list.html
{% for contact in contacts %}
{# Each "contact" is a Contact model object. #}
{{ contact.full_name|upper }}
...
{% endfor %}
基于模型类的视图,只需给paginate_by赋值(每页个数)就可以了,似乎是更简单:
class BookListView(generic.ListView):
model = Book
context_object_name = 'book_list'
template_name = 'catalog/book_list.html'
paginate_by = 10
模板是通用的,在模板中,可以调用is_paginated 判断是否有分页信息。在用page_obj对象实现分页。
{% block pagination %}
{% if is_paginated %}
{% endif %}
{% endblock %}
阅读原文:DJANGO技巧:利用PAGINATOR实现分页