自定制分页器组件(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="{}?{}">&laquo;</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="{}?{}">&raquo;</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

 

posted on 2018-08-09 22:26  kingon  阅读(294)  评论(0编辑  收藏  举报