python 自定义分页组件--Pagination
分页组件
武佩奇版
#!/usr/bin/env python # -*- coding:utf-8 -*- """ 分页组件应用: 1. 在视图函数中 queryset = models.Issues.objects.filter(project_id=project_id) page_object = Pagination( current_page=request.GET.get('page'), all_count=queryset.count(), base_url=request.path_info, query_params=request.GET ) issues_object_list = queryset[page_object.start:page_object.end] context = { 'issues_object_list': issues_object_list, 'page_html': page_object.page_html() } return render(request, 'issues.html', context) 2. 前端 {% for item in issues_object_list %} {{item.xxx}} {% endfor %} <nav aria-label="..."> <ul class="pagination" style="margin-top: 0;"> {{ page_html|safe }} </ul> </nav> """ class Pagination(object): def __init__(self, current_page, all_count, base_url, query_params, per_page=30, pager_page_count=11): """ 分页初始化 :param current_page: 当前页码 :param per_page: 每页显示数据条数 :param all_count: 数据库中总条数 :param base_url: 基础URL :param query_params: QueryDict对象,内部含所有当前URL的原条件 :param pager_page_count: 页面上最多显示的页码数量 """ self.base_url = base_url try: self.current_page = int(current_page) if self.current_page <= 0: self.current_page = 1 except Exception as e: self.current_page = 1 query_params = query_params.copy() query_params._mutable = True self.query_params = query_params self.per_page = per_page self.all_count = all_count self.pager_page_count = pager_page_count pager_count, b = divmod(all_count, per_page) if b != 0: pager_count += 1 self.pager_count = pager_count half_pager_page_count = int(pager_page_count / 2) self.half_pager_page_count = half_pager_page_count @property def start(self): """ 数据获取值起始索引 :return: """ return (self.current_page - 1) * self.per_page @property def end(self): """ 数据获取值结束索引 :return: """ return self.current_page * self.per_page def page_html(self): """ 生成HTML页码 :return: """ if self.all_count == 0: return "" # 如果数据总页码pager_count<11 pager_page_count if self.pager_count < self.pager_page_count: pager_start = 1 pager_end = self.pager_count else: # 数据页码已经超过11 # 判断: 如果当前页 <= 5 half_pager_page_count if self.current_page <= self.half_pager_page_count: pager_start = 1 pager_end = self.pager_page_count else: # 如果: 当前页+5 > 总页码 if (self.current_page + self.half_pager_page_count) > self.pager_count: pager_end = self.pager_count pager_start = self.pager_count - self.pager_page_count + 1 else: pager_start = self.current_page - self.half_pager_page_count pager_end = self.current_page + self.half_pager_page_count page_list = [] if self.current_page <= 1: prev = '<li><a href="#">上一页</a></li>' else: self.query_params['page'] = self.current_page - 1 prev = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url, self.query_params.urlencode()) page_list.append(prev) for i in range(pager_start, pager_end + 1): self.query_params['page'] = i if self.current_page == i: tpl = '<li class="active"><a href="%s?%s">%s</a></li>' % ( self.base_url, self.query_params.urlencode(), i,) else: tpl = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.query_params.urlencode(), i,) page_list.append(tpl) if self.current_page >= self.pager_count: nex = '<li><a href="#">下一页</a></li>' else: self.query_params['page'] = self.current_page + 1 nex = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.query_params.urlencode(),) page_list.append(nex) if self.all_count: tpl = "<li class='disabled'><a>共%s条数据,页码%s/%s页</a></li>" % ( self.all_count, self.current_page, self.pager_count,) page_list.append(tpl) page_str = "".join(page_list) return page_str
2.0版本
#!/usr/bin/env python # -*- coding:utf-8 -*- class Pagination(object): def __init__(self, request, data_set, per_page_data=10, nav_bar_num=11): """ 自定制分页器组件: 供调用属性:data、nav_bar 假设接收分页器处理后结果的对象为show_page show_page.data: 在当前页面上显示的数据集 show_page.nav_bar: 页码导航条 html生成代码 :param request: 一般来说是 request.GET 请求 :param data_set: 需要进行分页处理的数据对象,即总数据 :param per_page_data: 分页后每个页面所显示的数据条数,默认10条 :param nav_bar_num: 页码导航条上最多显示的页码数量 """ self.base_url = request.path_info self.query_params = request.GET.copy() # 保留原url上其他参数 # self.query_params._mutable = True self.per_page_data = per_page_data self.nav_bar_num = nav_bar_num # 列表、QuerySet等数据集 # 总数据量 try: total_data = data_set.count() except TypeError: total_data = len(data_set) self.total_data = total_data # 总页数 self.total_page, more = divmod(self.total_data, self.per_page_data) if more or not total_data: self.total_page += 1 # quotient, more = divmod(total_data, self.per_page_count) # self.total_page = quotient + 1 if more or not total_data else quotient # 当前页id current_page_id = request.GET.get('page') try: current_page_id = int(current_page_id) except (ValueError, TypeError): current_page_id = 1 self.current_page_id = current_page_id # 控制“.../?page=99999...”page参数乱入负数、太大数等情况(两个if,顺序不能反) if self.current_page_id > self.total_page: self.current_page_id = self.total_page if self.current_page_id < 1: self.current_page_id = 1 # 切片取出需要渲染在当前页面上的数据集 data_start = (self.current_page_id - 1) * self.per_page_data data_end = self.current_page_id * self.per_page_data self.data = data_set[data_start: data_end] # 方法变属性 @property def nav_bar(self): # 页码导航条最左边的页码id left_page_id = self.current_page_id - self.nav_bar_num // 2 # 页码导航条最右边的页码id right_page_id = self.current_page_id + self.nav_bar_num // 2 # 两端控制溢出 if left_page_id < 1: left_page_id, right_page_id = 1, self.nav_bar_num if right_page_id > self.total_page: left_page_id, right_page_id = self.total_page - self.nav_bar_num + 1, self.total_page # 数据量不足的情况下,控制页码导航条的显示 if self.total_page < self.nav_bar_num: left_page_id, right_page_id = 1, self.total_page prev_page_id = self.current_page_id - 1 if self.current_page_id != 1 else self.current_page_id next_page_id = self.current_page_id + 1 if self.current_page_id != self.total_page else self.current_page_id # 页码导航条部分的html标签代码 nav_bar_list = ['<nav aria-label="Page navigation"><ul class="pagination">', ] # 只更改url中原参数集中的page参数,其他参数还要编制在url上 self.query_params['page'] = 1 nav_bar_list.append('<li><a href="{}?{}">首页</a></li>'.format(self.base_url, self.query_params.urlencode())) self.query_params['page'] = prev_page_id nav_bar_list.append('<li><a href="{}?{}">«</a></li>'.format(self.base_url, self.query_params.urlencode())) for i in range(left_page_id, right_page_id + 1): self.query_params['page'] = i if i == self.current_page_id: tpl = '<li class="active"><a href="{}?{}">{}</a></li>' else: tpl = '<li><a href="{}?{}">{}</a></li>' nav_bar_list.append(tpl.format(self.base_url, self.query_params.urlencode(), i)) self.query_params['page'] = next_page_id nav_bar_list.append('<li><a href="{}?{}">»</a></li>'.format(self.base_url, self.query_params.urlencode())) self.query_params['page'] = self.total_page nav_bar_list.append('<li><a href="{}?{}">尾页</a></li>'.format(self.base_url, self.query_params.urlencode())) tpl = '<li><a class="disabled" style="color:#333;">共{}条数据,页码{}/{}页</a></li>' nav_bar_list.append(tpl.format(self.total_data, self.current_page_id, self.total_page)) nav_bar_list.append('</ul></nav>') nav_bar_html = ''.join(nav_bar_list) return nav_bar_html
效果