django自定义分页
功能:
1.分页
2.自动保留搜索条件
1.创建一个utils文件夹(用于存放工具,例如自定义分页功能),创建 page文件

2.自定义分页的类的参数
request 获取浏览器get请求的页码以及其他参数(?以后的)
current_page 当前页码
all_data 分页的数据,可迭代的
per_page_num 每页显示的数据
max_page_count 在浏览器中最多显示页码个数(例如:每次只显示多少页码)
3.通过参数算出的变量
all_pager, tmp = divmod(self.all_count, per_page_num) if tmp: all_pager += 1 all_pager 总页面数 max_page_count_half 当前页面左右两边显示页码个数(half 表示一半) self.params = copy.deepcopy(self.request.GET) 深copy,get请求参数,用于保留数据
4.生成显示页码的四种不同情况
1.如果总页码数小于最大显示页码个数,则范围是(1,总页码数)
2.当前页小于max_page_count_half,则范围是(1,max_page_count_half)
3.当翻到最后时,显示的页码要超过总页码时,就是说(当前页+max_page_count_half)>all_pager
则范围是(self.all_pager - self.max_page_count + 1, self.all_pager + 1)
4.在中间范围时,没有特殊情况,当前页加减max_page_count_half
则范围是(self.current_page - self.max_page_count_half,
self.current_page + self.max_page_count_half + 1)
5.保留搜索添加功能实现原理

要想保留用于的搜索条件,必须拿到request的请求,获取get或post,请求被Django重新解析成 QueryDict类型,无法被改变,通过 fromd django.http.request import QueryDict读源码,发现mutable = None,不可被改变,在深copy时,被改为False可以被改变
解决办法:我们只需要深copy,把copy的QueryDict变量,重新添加当前页面数据,用urlencode方法响应给浏览器(urlencode把键值对类型转化成字符串self.params.urlencode page=2(以空格来分割))
6.自定义分页器代码
class Pagination(object): def __init__(self, request, current_page, all_data, per_page_num=2, max_page_count=11): """ 封装分页相关数据 :param current_page: 当前页 :param all_count: 分页数据中的数据总条数 :param per_page_num: 每页显示的数据条数 :param max_page_count: 最多显示的页码个数 """ # 当前页是数值类型 try: current_page = int(current_page) # 如果不是报错,直接返回首页 except Exception as e: current_page = 1 # 如果当前页小于1则返回首页 if current_page < 1: current_page = 1 self.current_page = current_page # 算出所有的数据数 self.all_count = len(all_data) # 每页显示的数据 self.per_page_num = per_page_num # 总页码 # divmod 求商取余 all_pager, tmp = divmod(self.all_count, per_page_num) if tmp: all_pager += 1 # 总页面数 self.all_pager = all_pager # 最大显示页码数 self.max_page_count = max_page_count # 左右两边显示页面个数 self.max_page_count_half = int((max_page_count - 1) / 2) self.request = request # 深copy请求,在querydict中添加数据,原生数据有保护限制无法添加,要把源码的参数改变,复制 import copy self.params = copy.deepcopy(self.request.GET) print('self.params',self.params, 'self.params.urlencode',self.params.urlencode(),type(self.params.urlencode()) ) ''' all_count=100 per_page_num =10 current_page start end 1 0 10 2 10 20 3 20 30 all_count=100 per_page_num =8 current_page start end 1 0 8 2 8 16 3 16 24 表达式: start= (current_page-1)*per_page_num end =current_page* per_page_num ''' # 起始和结束用于分割总数据 # 起始数据,(当前页码-1)*每页显示数据 @property def start(self): return (self.current_page - 1) * self.per_page_num # 结束数据,当前页码*每页显示数据 @property def end(self): return self.current_page * self.per_page_num # 条件1:如果总页码数小于11个(最大显示页码数),则显示的范围是(1,总页面数+1) def page_html(self): # 如果总页码 < 11个: if self.all_pager <= self.max_page_count: pageRange = range(1, self.all_pager + 1) # 总页码 > 11 else: # 条件2:当前页如果小于页面上最多显示(11-1)/2个页码,则显示范围是(1,最大显示页码数) if self.current_page <= self.max_page_count_half: pageRange = range(1, self.max_page_count + 1) # 当前页大于5 else: # 页码翻到最后时候(当前页码+两边显示页面数) 大于 总的页码数 if (self.current_page + self.max_page_count_half) > self.all_pager: # 条件3:显示范围是((总页码-最大显示页码数+1),总页码数+1) pageRange = range(self.all_pager - self.max_page_count + 1, self.all_pager + 1) else: # 在中间,显示范围是((当前页面-显示最大页码数),(当前页面+最大显示页码数+1)) pageRange = range(self.current_page - self.max_page_count_half, self.current_page + self.max_page_count_half + 1) # 构建分页页码的html page_html_list = [] self.params["page"] = 1 first_page = '<nav aria-label="Page navigation"><ul class="pagination"><li><a href="?%s">首页</a></li>' % ( self.params.urlencode(),) page_html_list.append(first_page) self.params["page"] = self.current_page - 1 if self.current_page <= 1: prev_page = '<li class="disabled"><a href="#">上一页</a></li>' else: prev_page = '<li><a href="?%s">上一页</a></li>' % (self.params.urlencode(),) page_html_list.append(prev_page) # self.params: ["page":9,"a":1,"b":2] for i in pageRange: self.params["page"] = i if i == self.current_page: temp = '<li class="active"><a href="?%s">%s</a></li>' % (self.params.urlencode(), i,) else: temp = '<li><a href="?%s">%s</a></li>' % (self.params.urlencode(), i,) page_html_list.append(temp) self.params["page"] = self.current_page + 1 if self.current_page >= self.all_pager: next_page = '<li class="disabled"><a href="#">下一页</a></li>' else: next_page = '<li><a href="?%s">下一页</a></li>' % (self.params.urlencode(),) page_html_list.append(next_page) self.params["page"] = self.all_pager last_page = '<li><a href="?%s">尾页</a></li> </ul></nav>' % (self.params.urlencode()) page_html_list.append(last_page) return ''.join(page_html_list)
7.使用自定义分页器代码
from stark.utils.page import Pagination current_page = self.request.GET.get("page", 1) self.pagination = Pagination(self.request, current_page, self.queryset, per_page_num=self.config_obj.per_page_num or 5) # 切分数据,当数据库中数据很多时,没有要所有的都要取出来,如何通过索引部分取出??? queryset = self.queryset[self.pagination.start:self.pagination.end]

浙公网安备 33010602011771号