自定制分页器组件(Pagination)
1、封装分页器
#!/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
2、在视图函数中调用
from utils.pagination import Pagination def show_books(request): book_list = models.Books.objects.all() # book_list = models.Books.objects.all().value_list('title', 'authors') show_obj = Pagination(request, book_list) return render(request, 'books.html', {'show_obj': show_obj})
3、在模板html中调用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/css/bootstrap/bootstrap3.3.7-min.css"> </head> <body> <div class="container"> <table class="table table-bordered"> <thead> <tr> <td>序号</td> <td>ID</td> <td>书名</td> </tr> </thead> <tbody> {% for book in show_obj.data %} <tr> <td>{{ forloop.counter }}</td> <td>{{ book.id }}</td> <td>{{ book.title }}</td> </tr> {% endfor %} </tbody> </table> {{ show_obj.nav_bar|safe }} </div> </body> </html>
ok