30 自定义分页组件

基于bootstrap V3 应用
pager.py:

"""
如果想要使用分页,需要以下两个步骤

def xxx():
    queryset = models.TransactionRecord.objects.filter(customer_id=pk, customer__active=1).order_by('-id')

    pager = Pagination(request, queryset)

    return render(request, 'customer_charge.html', {'pager': pager})

页面上:
{% for row in pager.queryset %}
    {{row.id}}
    ...
{% endfor %}

<ul class="pagination">
    {{ pager.html }}
</ul>

"""
import copy
from django.utils.safestring import mark_safe


class Pagination(object):
    """分页"""

    def __init__(self, request, query_set, per_page_count=10):
        self.query_dict = copy.deepcopy(request.GET)
        self.query_dict._mutable = True
        self.query_set = query_set

        total_count = query_set.count()  # 总数据条数
        # 计算出总共有多少页面
        self.total_count = total_count
        self.total_page, div = divmod(total_count, per_page_count)
        if div:
            self.total_page += 1

        page = request.GET.get('page')

        if not page:
            page = 1
        else:
            if not page.isdecimal():
                page = 1
            else:
                page = int(page)
                if page <= 0:
                    page = 1
                else:
                    if page > self.total_page:
                        page = self.total_page

        self.page = page
        self.per_page_count = per_page_count

        self.start = (page - 1) * per_page_count
        self.end = page * per_page_count

    def html(self):
        pager_list = []
        if not self.total_count:
            return ''
        # 极值问题:总共的页码数量
        if self.total_page <= 11:
            start_page = 1
            end_page = self.total_page
        else:
            # 总页码比较多,判断当前页 <=6 : 1~11
            if self.page <= 6:
                start_page = 1
                end_page = 11
            else:
                if (self.page + 5) > self.total_page:
                    start_page = self.total_page - 10
                    end_page = self.total_page
                else:
                    start_page = self.page - 5
                    end_page = self.page + 5

        self.query_dict.setlist('page', [1])
        pager_list.append('<li><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode()))

        if self.page > 1:
            self.query_dict.setlist('page', [self.page - 1])
            pager_list.append('<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode()))

        for i in range(start_page, end_page + 1):
            self.query_dict.setlist('page', [i])
            if i == self.page:
                item = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
            else:
                item = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
            pager_list.append(item)

        if self.page < self.total_page:
            self.query_dict.setlist('page', [self.page + 1])
            pager_list.append('<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode()))

        self.query_dict.setlist('page', [self.total_page])
        pager_list.append('<li><a href="?{}">末页</a></li>'.format(self.query_dict.urlencode()))

        pager_list.append('<li class="disabled"><a>数据共{}条{}页</a></li>'.format(self.total_count, self.total_page))
        pager_string = mark_safe(''.join(pager_list))

        return pager_string

    def queryset(self):
        if self.total_count:
            return self.query_set[self.start: self.end]
        return self.query_set

pagination.py--> start组件使用

"""
使用方式:
视图:
    def changelist_view(self, request):
        """列表页面"""
        # 从数据库中获取所有的数据--->处理分页
        all_count = self.model_class.objects.all().count()
        query_params = request.GET.copy()
        query_params._mutable = True  # 可以被修改

        pager = Pagination(
            current_page=request.GET.get("page"),
            all_count=all_count,
            base_url=request.path_info,
            query_params=query_params,
            per_page=self.per_page_count,
        )

        data_list = self.model_class.objects.all()[pager.start: pager.end]
		return render(request, 'changelist.html',{'data_list': data_list,'pager': pager})

页面上:
<ul class="pagination">
    {{ pager.page_html|safe }}
</ul>
"""


class Pagination(object):
    def __init__(self, current_page, all_count, base_url, query_params, per_page=20, 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:
                raise Exception()
        except Exception as e:
            self.current_page = 1
        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:
        """
        # 如果数据总页码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)
        page_str = "".join(page_list)
        return page_str
posted @ 2022-10-10 16:54  角角边  Views(32)  Comments(0Edit  收藏  举报