django Paginator 让分页变得完美

参考大佬地址:https://www.zmrenwu.com/courses/django-blog-tutorial/materials/21/

类视图

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import ListView
from base.models import Project, Sign, Environment, Interface, Case, Plan, Report

@method_decorator(login_required, name='dispatch')  # 类装饰器,需要用 method_decorator 包一下,并指定 类方法
class ReportPage(ListView): # 继承ListView
    model = Report # 执行要查询的表名
    template_name = 'base/report_page/report_page.html' # 指定模板
    context_object_name = 'object_list' # 指定模板中使用的数据变量名称
    paginate_by = 10 # 一页多少条数据

    def dispatch(self, *args, **kwargs): # 重写dispatch 函数,供 method_decorator 指向这个函数
        return super(ReportPage, self).dispatch(*args, **kwargs)

    def get_queryset(self): # 重写查询,添加查询的条件等...
        self.plan_id = self.request.GET.dict().get('plan_id', '')
        if self.plan_id:
            return Report.objects.filter(plan_id=self.plan_id).order_by('-report_id') # 倒序返回
        else:
            return Report.objects.all().order_by('-report_id')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({'plan_id': self.plan_id}) # 在返回的字典中可以添加数据
        paginator = context.get('paginator')
        page = context.get('page_obj')
        is_paginated = context.get('is_paginated')
        data = pagination_data(paginator, page, is_paginated) # 接收处理好的分页数据
        context.update(data)
        return context
pagination_data()函数 直接用的大佬的,没有做修改
def pagination_data(paginator, page, is_paginated):
    if not is_paginated:
        # 如果没有分页,则无需显示分页导航条,不用任何分页导航条的数据,因此返回一个空的字典
        return {}

    # 当前页左边连续的页码号,初始值为空
    left = []

    # 当前页右边连续的页码号,初始值为空
    right = []

    # 标示第 1 页页码后是否需要显示省略号
    left_has_more = False

    # 标示最后一页页码前是否需要显示省略号
    right_has_more = False

    # 标示是否需要显示第 1 页的页码号。
    # 因为如果当前页左边的连续页码号中已经含有第 1 页的页码号,此时就无需再显示第 1 页的页码号,
    # 其它情况下第一页的页码是始终需要显示的。
    # 初始值为 False
    first = False

    # 标示是否需要显示最后一页的页码号。
    # 需要此指示变量的理由和上面相同。
    last = False

    # 获得用户当前请求的页码号
    page_number = page.number

    # 获得分页后的总页数
    total_pages = paginator.num_pages

    # 获得整个分页页码列表,比如分了四页,那么就是 [1, 2, 3, 4]
    page_range = paginator.page_range

    if page_number == 1:
        # 如果用户请求的是第一页的数据,那么当前页左边的不需要数据,因此 left=[](已默认为空)。
        # 此时只要获取当前页右边的连续页码号,
        # 比如分页页码列表是 [1, 2, 3, 4],那么获取的就是 right = [2, 3]。
        # 注意这里只获取了当前页码后连续两个页码,你可以更改这个数字以获取更多页码。
        right = page_range[page_number:page_number + 2]

        # 如果最右边的页码号比最后一页的页码号减去 1 还要小,
        # 说明最右边的页码号和最后一页的页码号之间还有其它页码,因此需要显示省略号,通过 right_has_more 来指示。
        if right[-1] < total_pages - 1:
            right_has_more = True

        # 如果最右边的页码号比最后一页的页码号小,说明当前页右边的连续页码号中不包含最后一页的页码
        # 所以需要显示最后一页的页码号,通过 last 来指示
        if right[-1] < total_pages:
            last = True

    elif page_number == total_pages:
        # 如果用户请求的是最后一页的数据,那么当前页右边就不需要数据,因此 right=[](已默认为空),
        # 此时只要获取当前页左边的连续页码号。
        # 比如分页页码列表是 [1, 2, 3, 4],那么获取的就是 left = [2, 3]
        # 这里只获取了当前页码后连续两个页码,你可以更改这个数字以获取更多页码。
        left = page_range[(page_number - 3) if (page_number - 3) > 0 else 0:page_number - 1]

        # 如果最左边的页码号比第 2 页页码号还大,
        # 说明最左边的页码号和第 1 页的页码号之间还有其它页码,因此需要显示省略号,通过 left_has_more 来指示。
        if left[0] > 2:
            left_has_more = True

        # 如果最左边的页码号比第 1 页的页码号大,说明当前页左边的连续页码号中不包含第一页的页码,
        # 所以需要显示第一页的页码号,通过 first 来指示
        if left[0] > 1:
            first = True
    else:
        # 用户请求的既不是最后一页,也不是第 1 页,则需要获取当前页左右两边的连续页码号,
        # 这里只获取了当前页码前后连续两个页码,你可以更改这个数字以获取更多页码。
        left = page_range[(page_number - 3) if (page_number - 3) > 0 else 0:page_number - 1]
        right = page_range[page_number:page_number + 2]

        # 是否需要显示最后一页和最后一页前的省略号
        if right[-1] < total_pages - 1:
            right_has_more = True
        if right[-1] < total_pages:
            last = True

        # 是否需要显示第 1 页和第 1 页后的省略号
        if left[0] > 2:
            left_has_more = True
        if left[0] > 1:
            first = True

    data = {
        'left': left,
        'right': right,
        'left_has_more': left_has_more,
        'right_has_more': right_has_more,
        'first': first,
        'last': last,
    }

    return data

html模板

{% if is_paginated %}
                    <ul class="pagination">
                        {% if first %}
                            <li class="page"><a href="?plan_id={{ plan_id }}&page=1">1</a></li>
                        {% endif %}
                        {% if left %}
                            {% if left_has_more %}
                                <li class="page"><a href="javascript:void(0)">...</a></li>
                            {% endif %}
                            {% for i in left %}
                                <li class="page"><a href="?plan_id={{ plan_id }}&page={{ i }}">{{ i }}</a></li>
                            {% endfor %}
                        {% endif %}
                        <li class="page"><a href="javascript:void(0)" class="active"> {{ page_obj.number }}</a></li>
                        {% if right %}
                            {% for i in right %}
                                <li class="page"><a href="?plan_id={{ plan_id }}&page={{ i }}">{{ i }}</a></li>
                            {% endfor %}
                            {% if right_has_more %}
                                <li class="page"><a href="javascript:void(0)">...</a></li>
                            {% endif %}
                        {% endif %}
                        {% if last %}
                            <li class="page"><a
                                    href="?plan_id={{ plan_id }}&page={{ paginator.num_pages }}">{{ paginator.num_pages }}</a>
                            </li>
                        {% endif %}

                    </ul>
                {% endif %}

分页完成示例:

原文地址:https://www.cnblogs.com/changqing8023/p/11212678.html