一、django内置分页
from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger L = [] for i in range(999): L.append(i) # 模拟数据库 生成数据 def index(request): current_page = request.GET.get('page') # 通过get请求得到当前请求的页数 paginator = Paginator(L, 10) # 实例化传入俩个参数(所有数据,当页显示条数) # per_page: 每页显示条目数量 # count: 数据总个数 # num_pages:总页数 # page_range:总页数的索引范围,如: (1,10),(1,200) # page: page对象 try: posts = paginator.page(current_page)# 传入当前页码,观源码可得实例化了一个Page对象 # has_next 是否有下一页 # next_page_number 下一页页码 # has_previous 是否有上一页 # previous_page_number 上一页页码 # object_list 分页之后的数据列表 # number 当前页 # paginator paginator对象 except PageNotAnInteger: # 不是数字 posts = paginator.page(1) except EmptyPage: # 超出页码范围 posts = paginator.page(paginator.num_pages) return render(request, 'index.html', {'posts': posts}) # posts封装了一些方法
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <ul> {% for item in posts %} <li>{{ item }}</li> {% endfor %} </ul> <div class="pagination"> <span class="step-links"> {% if posts.has_previous %} <a href="?p={{ posts.previous_page_number }}">上一页</a> {% endif %} <span class="current"> Page {{ posts.number }} of {{ posts.paginator.num_pages }}. </span> {% if posts.has_next %} <a href="?p={{ posts.next_page_number }}">下一页</a> {% endif %} </span> </div> </body> </html>
二、django内置分页的拓展
from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger user = [] for i in range(1, 1001): dic = {'name': 'root' + str(i), 'pwd': i} user.append(dic) class DiyPaginator(Paginator): def __init__(self, current_page,max_pager_num, *args, **kwargs): """ :param current_page: 当前页码 :param max_pager_num: 显示页码个数的最大值 :param args: :param kwargs: """ self.current_page = int(current_page) self.max_pager_num = int(max_pager_num) super(DiyPaginator,self).__init__(*args,**kwargs) def pager_num_range(self): # 需要的参数 # 当前页码 self.current_page # 页码数量 self.max_pager_num # 总页数 self.num_pages # 如果总页数小于页码个数最大值的情况 if self.num_pages < self.max_pager_num: return range(1,self.num_pages+1) # 返回 从 1 到 总页数 # 如果总页数大于页码数量且当前所选页码小于页码数量的一半 part = self.max_pager_num//2 if self.current_page <= part: return range(1,self.max_pager_num+1) # 返回 从 1 到 页码个数最大值 # 如果当前页码加一半的页码 大于 总页数 if (self.current_page+part) > self.num_pages: # 返回 从总页数-最大页码数 到 总页数 range的用法在此不作解释 # 例如 96页+5页 超出总页数 则返回的范围是 从 总页数-最大页码数量+1 到 总页数+1 return range(self.num_pages-self.max_pager_num+1,self.num_pages+1) # 其余情况从 当前页码减去显示页码的平均值开始 到 当前页码加显示页码的平均值(并加一)结束 return range(self.current_page-part,self.current_page+part+1) def index(request): p = request.GET.get('page') start = (int(p)-1)*10 end = int(p)*10 data = user[start:end] return render(request,'index.html',{'data':data,'user':user}) def index1(request): current_page = request.GET.get('page') paginator = DiyPaginator(current_page, 9, user, 10) # Paginator所封装的方法 # per_page: 每页显示条目数量 # count: 数据总个数 # num_pages:总页数 # page_range:总页数的索引范围,如: (1,10),(1,200) # page: page对象 try: posts = paginator.page(current_page) # has_next 是否有下一页 # next_page_number 下一页页码 # has_previous 是否有上一页 # previous_page_number 上一页页码 # object_list 分页之后的数据列表 # number 当前页 # paginator paginator对象 except PageNotAnInteger: # 不是整形数字 posts = paginator.page(1) except EmptyPage: # 如果是空值 posts = paginator.page(paginator.num_pages) return render(request,'index1.html',{'posts':posts})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for row in posts.object_list %} <li>{{ row.name }}-{{ row.pwd }}</li> {% endfor %} </ul> {% include 'include/pager.html' %} </body> </html> ################################## include 组件代码 {% if posts.has_previous %} <a href="/index1?page={{ posts.previous_page_number }}">上一页</a> {% endif %} {% for num in posts.paginator.pager_num_range %} {% if num == posts.number %} <a style="color: red;font-size: 20px" href="/index1?page={{ num }}">{{ num }}</a> {% else %} <a href="/index1?page={{ num }}">{{ num }}</a> {% endif %} {% endfor %} {% if posts.has_next %} <a href="/index1?page={{ posts.next_page_number }}">下一页</a> {% endif %} <span> 当前页:{{ posts.number }} 总页数:{{ posts.paginator.num_pages }} </span>
三、自定义分页
· 创建处理分页数据的类
· 根据分页数据获取数据
· 输出分页HTML,即:[上一页] [1] [2] [3] [4] [5] [下一页] 或者额外的作出一些拓展也可以创建处理分页数据的类时,大致也需要四个参数。
1、为了减少服务器内存的负载,不再获取所有数据的,而是获得所有数据的总个数,然后再根据索引查数据库的内容
2、当前页码
3、每页显示的行数
4、页码显示的数量
对于页数的显示大致也可以归类为三种情况:
1、计算的总页数小于页码显示的数量
2、计算的总页数大于页码显示的数量
a、当前页数小于页码数量的一半
b、当前页数加页码数量的一半超出总页数的范围
3、正常情况
从当前页数 减 一半页码数量 到 当前页数 加 一半页码数量
class Pagination(object): def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=9): """ :param totalCount: 所有数据总个数 :param currentPage: 当前页数 :param perPageItemNum: 每页显示行数 :param maxPageNum: 最多显示页码个数 """ self.total_count = totalCount # 对当前的页码进行一次异常捕获 try: currentPage = int(currentPage) if currentPage <= 0: currentPage = 1 self.current_page = currentPage except Exception: self.current_page = 1 self.per_page_item_num = perPageItemNum self.max_page_num = maxPageNum @property def start(self): # 数据索引开始的值 return (self.current_page-1) * self.per_page_item_num @property def end(self): # 数据索引结束的值 return self.current_page * self.per_page_item_num @property def num_pages(self): """ 总页数 :return: """ # 得商取余得内置函数 x, o = divmod(self.total_count,self.per_page_item_num) if o == 0: return x return x + 1 @property def page_num_range(self): if self.num_pages < self.max_page_num: return range(1, self.num_pages+1) part = self.max_page_num//2 if self.current_page <= part: return range(1,self.max_page_num+1) if (self.current_page+part) > self.num_pages: return range(self.num_pages-self.max_page_num+1, self.num_pages+1) return range(self.current_page-part, self.current_page+part+1) def page_str(self): page_list = [] first = "<li><a href='/index2/?page=1'>首页</a></li>" page_list.append(first) if self.current_page == 1: prev_page = "<li><a href='#'>上一页</a></li>" else: prev_page = "<li><a href='/index2/?page=%s'>上一页</a></li>" %(self.current_page-1) page_list.append(prev_page) for i in self.page_num_range: if i == self.current_page: temp = "<li class='active'><a href='/index2/?page=%s'>%s</a></li>" %(i,i) else: temp = "<li><a href='/index2/?page=%s'>%s</a></li>" % (i, i) page_list.append(temp) if self.current_page == self.num_pages: next_page = "<li><a href='#'>下一页</a></li>" else: next_page = "<li><a href='/index2/?page=%s'>下一页</a></li>" %(self.current_page+1) page_list.append(next_page) last = "<li><a href='/index2/?page=%s'>尾页</a></li>" %self.num_pages page_list.append(last) return ''.join(page_list) 复制代码
def index2(request): from page.diypage import Pagination current_page = request.GET.get('page') page_obj = Pagination(1000,current_page) data_list = user[page_obj.start:page_obj.end] return render(request,'index2.html',{ 'data' : data_list, 'page_obj' : page_obj })
# 本页面引用了bootstrap样式 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css" /> </head> <body> <ul> {% for row in data %} <li>{{ row.name }}-{{ row.pwd }}</li> {% endfor %} </ul> {% for i in page_obj.pager_num_range %} <a href="/index2/?page={{ i }}">{{ i }}</a> {% endfor %} <hr/> <ul class="pagination pagination-sm"> {{ page_obj.page_str|safe }} </ul> <div style="height: 300px;"></div> </body> </html>