django自定义分页

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]
 

 

posted @ 2019-04-18 08:34  左小白  阅读(66)  评论(0)    收藏  举报