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
View Code

 

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="{}?{}">&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
View Code

 

效果

 

posted @ 2020-03-06 17:07  hanfe1  阅读(304)  评论(0编辑  收藏  举报