django分页功能实现
一、django内置分页模块介绍
django内置的分页功能需要引入内置模块from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
Paginator是一个类,可实例化出一个对象,实例化的对象中封存了以下属性,示例paginator = Paginator(所有数据,每页显示数量)
per_page: 每页显示数量
count: 数据总个数
num_pages:总页数
page_range:总页数的索引范围,如: (1,10),(1,200)
page对象,示例paginator.page(current_page)
而page对象中也封存了以下属性
object_list:分页之后的数据列表,已经切片好的数据
has_next:是否有下一页
next_page_number 下一页页码
has_previous 是否有上一页
previous_page_number 上一页页码
number 当前页
paginator对象
二、扩展django内置分页功能
#生成数据 value_list=[] for i in range(1,501): temp = {'name':'root'+str(i),'age':i} value_list.append(temp) #自定义paginator对象,继承python自带的Paginator对象 class customePaginator(Paginator): def __init__(self,current_page,show_page_number,*args,**kwargs):#传入参数为当前页、页面显示的页码数 self.current_page = int(current_page) self.show_page_number = int(show_page_number) super().__init__(*args,**kwargs) def page_number_range(self):#获取当前页面显示的页码范围 if self.num_pages < self.show_page_number: #如果数据总页数小于页面显示页码数,页面显示页码数范围为[1,总页数] return range(1,self.num_pages+1) part = int(self.show_page_number/2) if self.current_page <= part: #如果当前页小于页面显示页码数的一半,页面显示页码数范围为[1,页面显示页码数],即当前页码很小的情况 return range(1,self.show_page_number+1) if (self.current_page+part)>self.num_pages:#如果当前页与页面显示页码数的一半的和大于总页数,页面显示页码数范围为[总页数-页面显示页码数,总页数],即当前页码很大的情况 return range(self.num_pages-self.show_page_number+1,self.num_pages+1) return range(self.current_page-part,self.current_page+part+1) #url对应的处理函数 def index1(request): per_page = 10 #每页显示10条数据 show_page_number = 11 #页面显示11个页码,建议为奇数 current_page = int(request.GET.get('p')) #获取当前页 post = customePaginator(current_page,show_page_number,value_list,per_page) #实例化自定义的类的对象 try: #实例化page对象 page = post.page(current_page) except PageNotAnInteger: #如果传入的参数不是整数,page为当前页 page = post.page(1) except EmptyPage: #如果传入参数大于总页数,page为最后一页 page = post.page(post.num_pages) return render(request,'index1.html',{'post':page})
<!--显示页面html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <ul> {% for p in post.object_list %} <li>{{ p.name }} {{ p.age }}</li> <!--页面显示内容--> {% endfor %} </ul> {% include 'include/pagecut.html' %} <!--页码部分,通过include引入--> </div> </body> </html> <!--页面模板,单独成一个html文件--> {% if post.has_previous %} <a href="index1?p={{ post.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a> {% endif %} {% for p in post.paginator.page_number_range %} {% if p == post.number %} <a href="index1?p={{ p }}" style="font-size: 20px">[{{ p }}]</a> {% else %} <a href="index1?p={{ p }}" >[{{ p }}]</a> {% endif %} {% endfor %} {% if post.has_next %} <a href="index1?p={{ post.next_page_number }}">下一页</a> {% else %} <a href="#">下一页</a> {% endif %} <span>{{ post.number }}/{{ post.paginator.num_pages }}</span>
三、自定义分页功能
#自定义Pagination对象,模拟django内置Paginator对象 class Pagination(object): def __init__(self,totalCount,currentPage,perPage=10,showPageNum=11):#初始化,四个参数分别表示数据总个数、当前页、每页显示个数、页面显示页码数 self.total_count = totalCount try: p = int(currentPage) if p <= 0: p = 1 self.current_page = p except Exception as e: self.current_page = 1 self.per_page = perPage self.show_page_num = showPageNum @property #页面显示数据的起始序列号 def start(self): return (self.current_page-1) * self.per_page @property #页面显示数据的结束序列号 def end(self): return self.current_page * self.per_page @property #数据总页数 def num_pages(self): a,b = divmod(self.total_count,self.per_page) if b ==0: return a return a+1 def page_number_range(self): #页面显示页码数的范围 if self.num_pages < self.show_page_num: return range(1,self.num_pages+1) part = int(self.show_page_num/2) if self.current_page <= part: return range(1,self.show_page_num+1) if (self.current_page+part)>self.num_pages: return range(self.num_pages-self.show_page_num+1,self.num_pages+1) return range(self.current_page-part,self.current_page+part+1) def page_str(self): #生成页面显示页码的html串 page_list = [] first = "<li><a href='index2?p=1'>首页</a></li>" page_list.append(first) if self.current_page == 1: prev = "<li><a href='#'>上一页</a></li>" else: prev = "<li><a href='index2?p=%s'>上一页</a></li>" % (self.current_page - 1,) page_list.append(prev) for i in self.page_number_range(): if i == self.current_page: temp = "<li class='active'><a href='index2?p=%s'>%s</a></li>" % (i, i) else: temp = "<li><a href='index2?p=%s'>%s</a></li>" % (i, i) page_list.append(temp) if self.current_page == self.num_pages: next = "<li><a href='#'>下一页</a></li>" else: next = "<li><a href='index2?p=%s'>下一页</a></li>" % (self.current_page + 1,) page_list.append(next) last = "<li><a href='index2?p=%s'>尾页</a></li>" % (self.num_pages,) page_list.append(last) print(page_list) return ''.join(page_list) #url对应的处理函数 def index2(request): from app01.page import Pagination current_page = request.GET.get('p') page_obj = Pagination(500,current_page) data_list = value_list[page_obj.start:page_obj.end] return render(request,'index2.html',{'data':data_list,'page_obj':page_obj})
<!--页面html文件--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.css"> </head> <body> <ul> {% for d in data %} <li>{{ d.name }} {{ d.age }}</li> <!--页面显示内容--> {% endfor %} </ul> <ul class="pagination pagination-sm"> <!--引用bootstrap的页码样式--> {{ page_obj.page_str|safe}} <!--页码部分--> </ul> </body> </html>