Paginator类
Paginator类的作用是将数据分割成若干份,在前端以分页的形式展示。当我们实例化一个Paginator类,需要给Paginator传递两个参数。第一个参数是数据源,可以是列表、元组以及查询结果集QuerySet。第二个参数传递一个整数,表示每夜显示的数据数量。
# Paginator基本写法
data_list = Book_all.objects.all() # 假定data_list获取数据库中的信息
paginator = Paginator(data_list,10) # data_list为数据源,每页显示10条数据
Paginator类有三个常用的属性:
count:所有页面的对象总数
num_pages:页面总数
page_range:下表从1开始的页数范围迭代器
Page对象
Paginator类提供一个**page(number)**函数,该函数返回一个Page对象。参数number表示第几个分页,如果number=1,那么page()返回的对象是第一分页的Page对象。在前端页面中显示数据,主要都是基于Page对象。
# 使用paginator对象返回第一页的page对象
books = paginator.page(1)
Page对象有三个常用属性:
object_list:当前页面上所有对象的列表
numberv:当前页的序号,从1开始计数
paginator:当前Page对象所属的Paginator对象
Page对象还有几个常用的函数:
has_next():判断是否还有下一页,有的话返回True
has_previous():判断是否还有上一页,有的话返回True
has_other_pages():判断是否上一页或下一页,有的话返回True
next_page_number():返回下一页的页码,如果不存在,抛出InvalidPage异常
previous_page_number():返回上一页的页码,如果不存在,抛出InvalidPage异常
应用案例
下面是自己编写的Demo程序,介绍Paginator和Page的基本使用。先创建基本的Model模型数据,在View中获取需要展示的全部数据,然后使用Paginator类对数据进行分页,最后返回第1个页面的page对象。page对象的作用很大,一方面显示当前分页数据,还提供获取后续页面数据的接口。
# models.py
from django.db import models
class Book(models.Model):
"""图书模型"""
title = models.CharField('图书',max_length=64)
price = models.CharField('价格',max_length=32)
pub_date = models.DateField('出版日期',auto_now_add=True)
class Meta:
verbose_name = '图书'
verbose_name_plural = '图书管理'
def __str__(self):
return self.title
# views.py
from django.shortcuts import render,redirect
from book.models import Book
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def book_list(request):
"""图书管理"""
book_all = Book.objects.all() # 获取book表中的所有数据
# 分页功能
paginator = Paginator(book_all,10) # 实例化一个Paginator,设置每页显示10条数据
page = request.GET.get('page') # 获取url后面page参数的值,首页不显示page参数, 默认值是1
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1) # 如果请求的页数不是整数,返回第一页
except EmptyPage:
contacts = paginator.page(paginator.num_pages) # 如果请求的页数不在合法的页数范围内,返回结果的最后一页。
context = {
'contacts':contacts,
}
return render(request,'book_list.html',context)
# book_list.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>Django数据分页演示</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
</head>
<body>
<table>
<thead>
<tr>
<th>编号</th>
<th>图书</th>
<th>价格</th>
<th>出版日期</th>
</tr>
</thead>
<tbody>
{% for books in contacts %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ books.title }}</td>
<td>{{ books.price }}</td>
<td>{{ books.pub_date }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
{% for page_num in contacts.paginator.page_range %}
<a {% if contacts.number == page_num %}class="active"{% endif %} href="?page={{ page_num }}">{{ page_num }}</a>
{% endfor %}
<a {% if contacts.has_previous %}href="?page={{ contacts.previous_page_number }}"{% endif %}>上一页</a>
<a {% if contacts.has_next %}href="?page={{ contacts.next_page_number }}"{% endif %}>下一页</a>
<span>页数:{{ contacts.number }}/{{ contacts.paginator.num_pages }}</span>
</div>
</body>
</html>
拿到视图传递过来的contacts(contacts是一个Page对象),模版中使用contacts根据页面情况展示上一页、下一页、总页数、当前页码
运行结果
封装代码
当使用分页功能的需求变多以后,封装代码就变得尤为重要了。新建一个page.py(名字和位置随意),自定义一个分页函数
# page.py
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def page_list(data_all,page,num):
"""数据分页"""
paginator = Paginator(data_all, num) # 实例化一个Paginator,data_all为数据源,num为每页显示数量
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1) # 如果请求的页数不是整数,返回第一页
except EmptyPage:
contacts = paginator.page(paginator.num_pages) # 如果请求的页数不在合法的页数范围内,返回结果的最后一页。
return contacts
在views.py中引用page.py中的page_list函数,并传入参数
# views.py
from django.shortcuts import render
from sales.models import Order
from apps.page import page_list # 引用分页的自定义函数
def order(request):
"""销售订单-列表"""
order_temp = Order.objects.all().order_by('-id')
# 分页功能
page = request.GET.get('page') # 获取url后面page参数的值,首页不显示page参数, 默认值是1
pages = page_list(order_temp, page, 10)
context = {
'pages':pages,
}
return render(request,'sales/sales.html',context)
前端新建一个page.html作公共分页模版,使用{% include 'page_list.html' %}来调用,这里注意:前端模版也是用pages变量来遍历数据。
# page_list.html
<div class="pagelist">
{% for page_num in pages.paginator.page_range %}
<a {% if pages.number == page_num %}class="current"{% endif %} href="?page={{ page_num }}">{{ page_num }}</a>
{% endfor %}
<a {% if pages.has_previous %}href="?page={{ pages.previous_page_number }}"{% endif %}>上一页</a>
<a {% if pages.has_next %}href="?page={{ pages.next_page_number }}"{% endif %}>下一页</a>
<span>页数:{{ pages.number }}/{{ pages.paginator.num_pages }}</span>
</div>