• Django框架-管理后台项目之分页实现


    一、自定义分页

    分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应在数据库表中的起始位置。

    1、设定煤业显示的数据条数

    2、用户输入页码(第一页,第二页...)

    3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

    4、在数据表中根据起始位置取值,页面上输出数据


    前面那样会在页面中生成所有的页码,但实际需要是设定指定数量的页码,格式如 [上一页][1][2][3][4][5][下一页]

    1、设定每页显示数据条数

    2、用户输入页码

    3、设定显示多少页号

    4、获取当前数据总条数

    5、根据设定显示多少页号和数据总条数计算出总页数

    6、根据设定的每页显示条数和当前页码数,计算出需要取数据表的起始位置

    7、在数据表中根据起始位置取值,页面上输出数据

    8、输出分页html,如:[上一页][1][2][3][4][5][下一页]

    urls.py

    urlpatterns = [
        url(r'page/, views.page),   
    ]

    customer.html

    {% load static %}
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="icon" href="{% static 'imgs/aimp_logo_48px_.ico' %}">
        {% block title %}
            {#下面的是改网页的标题上的图标#}
            <title>Template</title>
        {% endblock %}
    
        <!-- Bootstrap core CSS -->
        <link href="{% static 'plugin/bootstrap3.7/css/bootstrap.min.css' %}" rel="stylesheet">
        <!-- font_awesome CSS -->
        <link rel="stylesheet" href="{% static 'plugin/font-awesome-4.7.0/css/font-awesome.min.css' %}">
        <!-- Custom styles for this template网上模板定义的css样式 -->
        <link href="{% static 'css/dashboard.css' %}" rel="stylesheet">
    
        {% block custom_css %}
            {#自定义css留白#}
        {% endblock %}
    
    </head>
    
    <body>
    {#导航组件#}
    {% include 'layout/navbar.html' %}
    
    {#内容区#}
    <div class="container-fluid">
        <div class="row">
            {#左侧边栏#}
            <div class="col-sm-3 col-md-2 sidebar">
                <ul class="nav nav-sidebar">
                    <li class="active"><a href="{% url 'app_crm:customer_list' %}">客户信息表 <span
                            class="sr-only">(current)</span></a></li>
                    <li><a href="#">销售</a></li>
                    <li><a href="#">老师</a></li>
                    <li><a href="#">学生</a></li>
                </ul>
            </div>
            {#右边内容展示区,表单及面板#}
            <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
                {% block content %}
                    <h2 class="sub-header">客户信息展示表</h2>
                    <div class="table-responsive">
                        <table class="table table-striped">
                            <thead>
                            <tr>
                                <th>序号</th>
                                <th>账户</th>
                                <th>密码</th>
                            </tr>
                            </thead>
                            <tbody>
                            {% for u in user %}
                                <tr>
                                    <td>{{ forloop.counter }}</td>
                                    <td>{{ u.name }}</td>
                                    <td>{{ u.pwd }}</td>
                                </tr>
                            {% empty %}
                                <tr>
                                    <td colspan="3" class="text-center">暂无数据</td>
                                </tr>
                            {% endfor %}
                            </tbody>
                        </table>
                        {# 分页 #}
                        <nav aria-label="Page navigation" class="text-center">
                            <ul class="pagination">
                                <li>
                                    <a href="#" aria-label="Previous">
                                        <span aria-hidden="true">&laquo;</span>
                                    </a>
                                </li>
                                {% for page in total_page %}
                                    {# 此处也可以设计url为分组的形式传递页码给后台{% url 'app_crm:base' page %}#}
                                    <li><a href="{% url 'app_crm:base' %}?page={{ page }}">{{ page }}</a></li>
                                {% endfor %}
                                <li>
                                    <a href="#" aria-label="Next">
                                        <span aria-hidden="true">&raquo;</span>
                                    </a>
                                </li>
                            </ul>
                        </nav>
                    </div>
                {% endblock %}
            </div>
        </div>
    </div>
    
    
    <!-- Bootstrap core JavaScript -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script type="text/javascript" src="{% static 'plugin/jquery-3.3.1/jquery3.3.1.min.js' %}"></script>
    <script type="text/javascript" src="{% static 'plugin/bootstrap3.7/js/bootstrap.min.js' %}"></script>
    {#自定义js留白区域快#}
    {% block custom_js %}
    {% endblock %}
    </body>
    </html>
    html-前端循环生成页码

    views.py

     1 def page(request):
     2     """
     3     all_count: 总数据条数
     4     page_num: 每页显示数据条数,自定义
     5     total_page: 总页码数
     6     more:总数据条数% 每页数     ==》余数
     7     current_page: 当前页码,由前端点击时,将页码发回来
     8     """
     9     user = [{'name': 'sun%s' % i, 'pwd': 'pwd{}'.format(i)} for i in range(1, 302)]  # 测试数据源
    10     all_count = len(user)  # 拿到总数据条数
    11     page_num = 10  # 定义每页显示的数据条数
    12     total_page, more = divmod(all_count, page_num)  # 得出商和余数
    13     if more:  # 如果有余数,表示总页码要多加一个页码,否则就是整除
    14         total_page += 1
    15 
    16     try:
    17         current_page = int(request.GET.get('page'))
    18         if current_page <= 0:  # 因为不确定前端传过来的数字的准确性,可能没有或超过,负数所以要判断,一旦报错,就设置当前页为1
    19             raise ValueError()
    20     except Exception as e:
    21         current_page = 1
    22 
    23     # 所有数据和生成的标签页全部展示
    24     # 因为计划通过前端for循环产生标签,故需要传一个可迭代的数据即range(1,total_page+1),切片取头不取尾
    25     return render(request, 'layout/base.html', {'user': user, 'total_page': range(1, total_page + 1)})
    26 
    27 # 注:前端拿到user和total_page对象,对其for循环生成对应标签即可
    分页初版-显示所有数据和标签
     1 def page(request):
     2     """
     3     all_count: 总数据条数
     4     page_num: 每页显示数据条数,自定义
     5     total_page: 总页码数
     6     more:总数据条数% 每页数     ==》余数
     7     current_page: 当前页码,由前端点击时,将页码发回来
     8     start: 切片开始索引
     9     end: 切片结束索引
    10     页码数和切片之间的关系:
    11     第一页:  1  1   10        0   10            每页10条,切片从0开始,尾不取
    12              2  11  20        10   20
    13             3   21  30        20   30
    14             关系为:(当前页-1)*10  即 start = (current_page-1)*10
    15                                        end= current_page*page_num
    16     """
    17     user = [{'name': 'sun%s' % i, 'pwd': 'pwd{}'.format(i)} for i in range(1, 302)]
    18     all_count = len(user)
    19     page_num = 10  # 定义每页显示的数据条数
    20     total_page, more = divmod(all_count, page_num)  # 得出商和余数
    21     if more:  # 如果有余数,表示总页码要多加一个页码,否则就是整除
    22         total_page += 1
    23     try:
    24         current_page = int(request.GET.get('page'))
    25         # 因为不确定前端传过来的数字的准确性,可能没有或超过,负数所以要判断,一旦报错,就设置当前页为1
    26         if current_page <= 0:
    27             raise ValueError()
    28     except Exception as e:
    29         current_page = 1
    30     # 根据前端传过来的页码,计算给前端发送多少数据,限制数据条数
    31     start = (current_page - 1) * 10
    32     end = current_page * page_num
    33     
    34     return render(request, 'layout/base.html', {'user': user[start:end],   # 限制数据条数,根据需要给
    35                                                 'total_page': range(1, total_page + 1)})
    分页过滤版-根据前端需求页码给出对应数量的数据+所有页码标签
    def page(request):
        """
            all_count: 总数据条数
            page_num: 每页显示数据条数,自定义
            total_page: 总页码数
            more:总数据条数% 每页数     ==》余数
            current_page: 当前页码,由前端点击时,将页码发回来
            start: 切片开始索引
            end: 切片结束索引
            页码数和切片之间的关系:
            第一页:  1  1   10        0   10            每页10条,切片从0开始,尾不取
                     2  11  20        10   20
                    3   21  30        20   30
                    关系为:(当前页-1)*10  即 start_page = (current_page-1)*10
                                            end_page = current_page*page_num
            start_page:  起始页码数
            end_page: 终止页码数
            max_page_show:  每页最多展示几个分页,如7各分页:1 2 3 当前页 5 6 7
    
            """
        user = [{'name': 'sun%s' % i, 'pwd': 'pwd{}'.format(i)} for i in range(1, 302)]
        all_count = len(user)
        page_num = 10  # 定义每页显示的数据条数
        total_page, more = divmod(all_count, page_num)  # 得出商和余数
        if more:  # 如果有余数,表示总页码要多加一个页码,否则就是整除
            total_page += 1
        # 因为计划通过前端for循环产生标签,故需要传一个可迭代的数据即range(1,total_page+1),切片取头不取尾
        try:
            current_page = int(request.GET.get('page'))
            # 因为不确定前端传过来的数字的准确性,可能没有或超过,负数所以要判断,一旦报错,就设置当前页为1
            if current_page <= 0:
                raise ValueError()
        except Exception as e:
            current_page = 1
        # 根据前端传过来的页码,计算给前端发送多少数据,限制数据条数
        start = (current_page - 1) * 10
        end = current_page * page_num
        # 定义分页页码起始页码数,终止页码数,每个页面最大显示页码数
        max_page_show = 5  # 一般都定义为奇数,让中间的页(即当前页)左右对称
        half_page_show = max_page_show // 2
    
        # 将会出现几种情况:
        # 1、数据总页码数<= 定义的每个页面最大显示页码数max_page_show,就直接把所有的显示出来即可
        if total_page <= max_page_show:
            start_page = 1
            end_page = total_page
        else:
            # 2、当前页小于half_page_show时,排除会出现负数的情况,解决左边的问题
            if current_page <= half_page_show:  # 都要保证每个页面有max_page_show页
                start_page = 1
                end_page = max_page_show
            # 3、当前页+half_page_show > max_page_show 时,会出现没有数据,但会有页码,故需要排除掉
            elif current_page + half_page_show > total_page:
                start_page = total_page - max_page_show + 1
                # start_page = current_page - half_page_show +1
                end_page = total_page
            else:
                start_page = current_page - half_page_show
                end_page = current_page + half_page_show
        return render(request, 'layout/base.html', {'user': user[start:end],
                                                    'total_page': range(start_page, end_page + 1)
                                                    })  # 限制页面总显示页码数及根据需求页码给出对应数据
    分页进阶版-指定页面最大显示页码数,按需要给出对应条数据
    from django.shortcuts import render, reverse
    
    
        def base(request):
            """
            all_count: 总数据条数
            page_num: 每页显示数据条数,自定义
            total_page: 总页码数
            more:总数据条数% 每页数     ==》余数
            current_page: 当前页码,由前端点击时,将页码发回来
            start: 切片开始索引
            end: 切片结束索引
            页码数和切片之间的关系:
            第一页:  1  1   10        0   10            每页10条,切片从0开始,尾不取
                     2  11  20        10   20
                    3   21  30        20   30
                    关系为:(当前页-1)*10  即 start_page = (current_page-1)*10
                                            end_page = current_page*page_num
            start_page:  起始页码数
            end_page: 终止页码数
            max_page_show:  每个页面最大显示页码数,如7各分页:1 2 3 当前页 5 6 7
            """
            user = [{'name': 'sun%s' % i, 'pwd': 'pwd{}'.format(i)} for i in range(1, 302)]
            all_count = len(user)  # 得出数据总条数
            page_num = 10  # 定义每页显示的数据条数
            total_page, more = divmod(all_count, page_num)  # 得出商和余数
            if more:
                total_page += 1  # 如果有余数,表示总页码要多加一个页码
            try:
                current_page = int(request.GET.get('page'))
                # 因为不确定前端传过来的数字的准确性,可能没有或超过,负数,所以要判断,一旦报错,就设置当前页为1
                if current_page <= 0:
                    raise Exception('当前页码数字不符合规范')
            except Exception as e:
                current_page = 1
    
            # 根据前端传过来的页码,计算给前端发送多少数据,限制数据条数
            start = (current_page - 1) * page_num
            end = current_page * page_num
    
            # 定义分页页码起始页码数,终止页码数,每个页面最大显示页码数,实现每页固定页码数
            max_page_show = 5  # 一般都定义为奇数,让中间的页(即当前页)左右对称
            half_page_show = max_page_show // 2
    
            # 1、数据总页码数<= 定义的每个页面最大显示页码数max_page_show,就直接把所有的显示出来即可
            if total_page <= max_page_show:
                start_page = 1
                end_page = total_page
            else:
                # 2、当前页小于half_page_show时,排除会出现负数的情况,解决左边的问题
                if current_page <= half_page_show:  # 都要保证每个页面有max_page_show页
                    start_page = 1
                    end_page = max_page_show
                # 3、当前页+half_page_show > max_page_show 时,会出现没有数据,但会有页码,故需要排除掉
                elif current_page + half_page_show > total_page:
                    start_page = total_page - max_page_show + 1
                    # start_page = current_page - half_page_show +1
                    end_page = total_page
                else:
                    start_page = current_page - half_page_show
                    end_page = current_page + half_page_show
    
            """后端实现分页,前端只需接收只需接收字符串即可,故需要把生成得标签拼接起来"""
            html_list = []
            # 加上"首页"功能,即当前页与第一页相比【首页】【上一页】 1 2 3 4 5 【下一页】【末页】
            if current_page <= 1:
                first = '<li class="disabled"><a>首页</a></li>'
            else:
                first = '<li><a href="{}?page={}">首页</a></li>'.format(reverse('app_crm:base'), 1)
            html_list.append(first)
            # 加上"上一页"功能,即当前页与第一页相比 【首页】【上一页】 1 2 3 4 5 【下一页】【末页】
            if current_page <= 1:
                prev = '<li class="disabled"><a>上一页</a></li>'  # 当前页小于1时,上一页按钮禁止点击
            else:
                prev = '<li><a href="{}?page={}">上一页</a></li>'.format(reverse('app_crm:base'), current_page - 1)
            html_list.append(prev)
            # 生成分页页码标签
            for page in range(start_page, end_page + 1):
                if page == current_page:  # 加active类
                    li_html = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(reverse('app_crm:base'), page)
                else:
                    li_html = '<li><a href="{0}?page={1}">{1}</a></li>'.format(reverse('app_crm:base'), page)
                html_list.append(li_html)
            # 加上"下一页"功能,当前页与最后一页比较,即total_page
            if current_page >= total_page:
                next_page = '<li class="disabled"><a>下一页</a></li>'
            else:
                next_page = '<li><a href="{}?page={}">下一页</a></li>'.format(reverse('app_crm:base'), current_page + 1)
            html_list.append(next_page)
            # 加上"末页" 功能
            if current_page >= total_page:
                last = '<li class="disabled"><a>末页</a></li>'
            else:
                last = '<li><a href="{}?page={}">末页</a></li>'.format(reverse('app_crm:base'), total_page)
            html_list.append(last)
            html_str = "".join(html_list)  # 拼接成字符串
            from django.utils.html import format_html  # 后端声明发送的是安全的标签,将字符串编译成标签
            result = format_html(html_str)
            return render(request, 'layout/base.html', {'user': user[start:end],
                                                        'total_page': result
                                                        })  # 限制页面总显示页码数及根据需求页码给出对应数据
    分页终极版

    分页终极版是在后端循环生成分页标签,故前端只需引用即可{{result}} 即可。 

    {% load static %}
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <link rel="icon" href="{% static 'imgs/aimp_logo_48px_.ico' %}">
    
        {% block title %}
            <title>Template</title>
        {% endblock %}
    
        <!-- Bootstrap core CSS -->
        <link href="{% static 'plugin/bootstrap3.7/css/bootstrap.min.css' %}" rel="stylesheet">
        <!-- font_awesome CSS -->
        <link rel="stylesheet" href="{% static 'plugin/font-awesome-4.7.0/css/font-awesome.min.css' %}">
        <!-- Custom styles for this template网上模板定义的css样式 -->
        <link href="{% static 'css/dashboard.css' %}" rel="stylesheet">
    
        {% block custom_css %}
            {#自定义css留白#}
        {% endblock %}
    </head>
    
    <body>
    {#导航组件#}
    {% include 'layout/navbar.html' %}
    
    {#内容区#}
    <div class="container-fluid">
        <div class="row">
            {#左侧边栏#}
            <div class="col-sm-3 col-md-2 sidebar">
                <ul class="nav nav-sidebar">
                    <li class="active"><a href="{% url 'app_crm:customer_list' %}">客户信息表 <span
                            class="sr-only">(current)</span></a></li>
                    <li><a href="#">销售</a></li>
                    <li><a href="#">老师</a></li>
                    <li><a href="#">学生</a></li>
                </ul>
            </div>
            {#右边内容展示区#}
            <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
                {% block content %}
                    <h2 class="sub-header">客户信息展示表</h2>
                    <div class="table-responsive">
                        <table class="table table-striped">
                            <thead>
                            <tr>
                                <th>序号</th>
                                <th>账户</th>
                                <th>密码</th>
                            </tr>
                            </thead>
                            <tbody>
                            {% for u in user %}
                                <tr>
                                    <td>{{ forloop.counter }}</td>
                                    <td>{{ u.name }}</td>
                                    <td>{{ u.pwd }}</td>
                                </tr>
                            {% empty %}
                                <tr>
                                    <td colspan="3" class="text-center">暂无数据</td>
                                </tr>
                            {% endfor %}
                            </tbody>
                        </table>
                        {# 分页 #}
                        <nav aria-label="Page navigation" class="text-center">
                            <ul class="pagination">
                                {{ total_page }}
                            </ul>
                            <form action="">
                                    <span>去第</span>
                                    <label for="search_page"></label>
                                    <input id="search_page" name="page" type="text"  >
                                    <span></span>
                                    <input type="submit" class=" btn-primary" value="确定">
                            </form>
                        </nav>
                    </div>
                {% endblock %}
            </div>
        </div>
    </div>
    <script type="text/javascript" src="{% static 'plugin/jquery-3.3.1/jquery3.3.1.min.js' %}"></script>
    <script type="text/javascript" src="{% static 'plugin/bootstrap3.7/js/bootstrap.min.js' %}"></script>
    
    {% block custom_js %}
        {#自定义js留白区域快#}
    {% endblock %}
    </body>
    </html>
    终极html+分页数据+指定数量分页+搜索分页

    二、分页功能模块化,封装成一个类,供所有的页面使用

    在项目下建立一个包如utils,在里面建立一个py文件,如命名分页组件: pagination.py

    封装成分页组件,需要导入传参即可用

    """分页组件"""
    from django.utils.html import format_html  # 后端声明发送的是安全的标签,将字符串编译成标签
    
    
    class Pagination(object):
        """
            all_count: 总数据条数
            page_num: 每页显示数据条数,自定义
            total_page: 总页码数
            more:总数据条数% 每页数     ==》余数
            current_page: 当前页码,由前端点击时,将页码发回来
            start: 切片开始索引
            end: 切片结束索引
            页码数和切片之间的关系:
            第一页:  1  1   10        0   10            每页10条,切片从0开始,尾不取
                     2  11  20        10   20
                    3   21  30        20   30
                    关系为:(当前页-1)*10  即 start_page = (current_page-1)*10
                                            end_page = current_page*page_num
            start_page:  起始页码数
            end_page: 终止页码数
            max_page_show:  每个页面最大显示页码数,如7各分页:1 2 3 当前页 5 6 7  一般都定义为奇数,让中间的页(即当前页)左右对称
            base_url : 访问url地址
        """
    
        def __init__(self, request, base_url, all_count, page_num=10, max_page_show=5):
            # 获取需求页码
            try:
                current_page = int(request.GET.get('page'))
                if current_page <= 0:
                    raise Exception('当前页码数字不符合规范')
            except Exception as e:
                current_page = 1
    
            # 定义分页页码起始页码数,终止页码数,每个页面最大显示页码数,实现每页固定页码数
            self.max_page_show = max_page_show
            self.half_page_show = max_page_show // 2
            self.current_page = current_page
            self.all_count = all_count
            self.page_num = page_num
            self.base_url = base_url
    
            # 计算数据总条数
            self.total_page, more = divmod(self.all_count, self.page_num)  # 得出商和余数
            if more:
                self.total_page += 1  # 如果有余数,表示总页码要多加一个页码
        @property
        def start(self):
            # 根据前端传过来的页码,计算给前端发送多少数据,限制数据条数
            # 数据切片的起始索引和终止索引
            return (self.current_page - 1) * self.page_num
        @property
        def end(self):
            return self.current_page * self.page_num
        @property
        def html_str(self):
            #  计算起始页码数和终止页码数
            # 1、数据总页码数<= 定义的每个页面最大显示页码数max_page_show,就直接把所有的显示出来即可
            if self.total_page <= self.max_page_show:
                start_page = 1
                end_page = self.total_page
            else:
                # 2、当前页小于half_page_show时,排除会出现负数的情况,解决左边的问题
                if self.current_page <= self.half_page_show:  # 都要保证每个页面有max_page_show页
                    start_page = 1
                    end_page = self.max_page_show
                # 3、当前页+half_page_show > max_page_show 时,会出现没有数据,但会有页码,故需要排除掉
                elif self.current_page + self.half_page_show > self.total_page:
                    start_page = self.total_page - self.max_page_show + 1
                    # start_page = current_page - half_page_show +1
                    end_page = self.total_page
                else:
                    start_page = self.current_page - self.half_page_show
                    end_page = self.current_page + self.half_page_show
    
            """后端实现分页,前端只需接收只需接收字符串即可,故需要把生成得标签拼接起来"""
            html_list = []
            # 加上"首页"功能,即当前页与第一页相比【首页】【上一页】 1 2 3 4 5 【下一页】【末页】
            if self.current_page <= 1:
                first = '<li class="disabled"><a>首页</a></li>'
            else:
                first = '<li><a href="{}?page={}">首页</a></li>'.format(self.base_url, 1)
            html_list.append(first)
            # 加上"上一页"功能,即当前页与第一页相比 【首页】【上一页】 1 2 3 4 5 【下一页】【末页】
            if self.current_page <= 1:
                prev = '<li class="disabled"><a><上一页></a></li>'  # 当前页小于1时,上一页按钮禁止点击
            else:
                prev = '<li><a href="{}?page={}"><上一页></a></li>'.format(self.base_url, self.current_page - 1)
            html_list.append(prev)
            # 生成分页页码标签
            for page in range(start_page, end_page + 1):
                if page == self.current_page:  # 加active类
                    li_html = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, page)
                else:
                    li_html = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, page)
                html_list.append(li_html)
            # 加上"下一页"功能,当前页与最后一页比较,即total_page
            if self.current_page >= self.total_page:
                next_page = '<li class="disabled"><a><下一页></a></li>'
            else:
                next_page = '<li><a href="{}?page={}"><下一页></a></li>'.format(self.base_url, self.current_page + 1)
            html_list.append(next_page)
            # 加上"末页" 功能
            if self.current_page >= self.total_page:
                last = '<li class="disabled"><a>末页</a></li>'
            else:
                last = '<li><a href="{}?page={}">末页</a></li>'.format(self.base_url, self.total_page)
            html_list.append(last)
            html_str = "".join(html_list)  # 拼接成字符串
            result = format_html(html_str)
            return result

    此分页组件,项目下所有的app都可以使用,主要传参 request, base_url, all_count, page_num=10, max_page_show=5,

    分别为request,目标url,所有的数据条数,每页显示最大数据条数,默认10条,每页最多显示分页标签数,默认5个

    在app应用的views.py中引用:

    from utils.pagination import Pagination
    def base_test(request):
        base_url = request.path_info  # 获取当前url,也可以自定义
        page_obj = Pagination(request, base_url, len(users), 15, 11)
        total_page = page_obj.total_page
        return render(request, 'layout/base.html',
                      {'user_list': users[page_obj.start:page_obj.end],
                       'result': page_obj.html_str,
                       'total_page':total_page
                       })

    三、终极版:将搜索条件和标签页码放到url下,让标签显示的是筛选后的数据进行分页

    """分页组件"""
    from django.utils.html import format_html  # 后端声明发送的是安全的标签,将字符串编译成标签
    
    
    class Pagination(object):
        """
            all_count: 总数据条数
            page_num: 每页显示数据条数,自定义
            total_page: 总页码数
            more:总数据条数% 每页数     ==》余数
            current_page: 当前页码,由前端点击时,将页码发回来
            start: 切片开始索引
            end: 切片结束索引
            页码数和切片之间的关系:
            第一页:  1  1   10        0   10            每页10条,切片从0开始,尾不取
                     2  11  20        10   20
                    3   21  30        20   30
                    关系为:(当前页-1)*10  即 start_page = (current_page-1)*10
                                            end_page = current_page*page_num
            start_page:  起始页码数,一个页面中显示的分页标签
            end_page: 终止页码数
            max_page_show:  每个页面最大显示页码数,如7各分页:1 2 3 当前页 5 6 7  一般都定义为奇数,让中间的页(即当前页)左右对称
            base_url : 当前访问url地址
    
            query_params: 为了分页标签能带上搜索条件,让分页数据是从搜索条件来的
                搜索和分页要合并起来,不然搜索到对应数据,展示出来,但一旦点击分页标签,就会走分页的逻辑,不是拿搜索中的数据
                来分页,所以应该为分页标签加上搜索条件,当发点击搜索get请求后,会先走搜索,将筛选后的数据类表传给分页函数,再分页,
                当点击分页标签时会再次搜索,然后分页,而不是搜索条件为空,展示所有的数据
        """
    
        def __init__(self, request, base_url, all_count, page_num=10, max_page_show=5):
            # 获取需求页码
            try:
                current_page = int(request.GET.get('page'))
                if current_page <= 0:
                    raise Exception('当前页码数字不符合规范')
            except Exception as e:
                current_page = 1
    
            # 定义分页页码起始页码数,终止页码数,每个页面最大显示页码数,实现每页固定页码数
            self.max_page_show = max_page_show
            self.half_page_show = max_page_show // 2
            self.current_page = current_page
            self.all_count = all_count
            self.page_num = page_num
            self.base_url = base_url
    
            # 为了分页与搜索条件合并
            # request.GET.urlencode() 方法可以将url中?后面的查询条件按key=value完成拿出来 query=3
            # url合成格式为:?query=3&page=x
            # import copy
            # query_params = copy.deepcopy(request.GET)  # 是一个querySet字典,为防止对request.GET 的改变影响其它方法的调用,对其深拷贝
            # django自带的深拷贝方法
            query_params = request.GET.copy()
            self.query_params = query_params
            self.query_params._mutable = True  # 允许querySet字典变更
    
            # 计算数据总条数
            self.total_page, more = divmod(self.all_count, self.page_num)  # 得出商和余数
            if more:
                self.total_page += 1  # 如果有余数,表示总页码要多加一个页码
    
        @property
        def start(self):
            # 根据前端传过来的页码,计算给前端发送多少数据,限制数据条数
            # 数据切片的起始索引和终止索引
            return (self.current_page - 1) * self.page_num
    
        @property
        def end(self):
            return self.current_page * self.page_num
    
        @property
        def html_str(self):
            #  计算起始页码数和终止页码数
            # 1、数据总页码数<= 定义的每个页面最大显示页码数max_page_show,就直接把所有的显示出来即可
            if self.total_page <= self.max_page_show:
                start_page = 1
                end_page = self.total_page
            else:
                # 2、当前页小于half_page_show时,排除会出现负数的情况,解决左边的问题
                if self.current_page <= self.half_page_show:  # 都要保证每个页面有max_page_show页
                    start_page = 1
                    end_page = self.max_page_show
                # 3、当前页+half_page_show > max_page_show 时,会出现没有数据,但会有页码,故需要排除掉
                elif self.current_page + self.half_page_show > self.total_page:
                    start_page = self.total_page - self.max_page_show + 1
                    # start_page = current_page - half_page_show +1
                    end_page = self.total_page
                else:
                    start_page = self.current_page - self.half_page_show
                    end_page = self.current_page + self.half_page_show
    
            """后端实现分页,前端只需接收只需接收字符串即可,故需要把生成得标签拼接起来"""
            html_list = []
            # 加上"首页"功能,即当前页与第一页相比【首页】【上一页】 1 2 3 4 5 【下一页】【末页】
            if self.current_page <= 1:
                first = '<li class="disabled"><a>首页</a></li>'
            else:
                self.query_params['page'] = 1
                # first = '<li><a href="{}?page={}">首页</a></li>'.format(self.base_url, 1)
                # 为了search和page合并将page加入到query_params字典中,然后query_params.urlencode()拼接
                first = '<li><a href="{}?{}">首页</a></li>'.format(self.base_url, self.query_params.urlencode())
            html_list.append(first)
            # 加上"上一页"功能,即当前页与第一页相比 【首页】【上一页】 1 2 3 4 5 【下一页】【末页】
            if self.current_page <= 1:
                prev = '<li class="disabled"><a><上一页></a></li>'  # 当前页小于1时,上一页按钮禁止点击
            else:
                self.query_params['page'] = self.current_page - 1
                prev = '<li><a href="{}?{}"><上一页></a></li>'.format(self.base_url, self.query_params.urlencode())
            html_list.append(prev)
            # 生成分页页码标签
            for page in range(start_page, end_page + 1):
                self.query_params['page'] = page
                if page == self.current_page:  # 加active类
                    li_html = '<li class="active"><a href="{}?{}">{}</a></li>'.format(self.base_url,
                                                                                      self.query_params.urlencode(), page)
                else:
                    li_html = '<li><a href="{}?{}">{}</a></li>'.format(self.base_url, self.query_params.urlencode(), page)
                html_list.append(li_html)
            # 加上"下一页"功能,当前页与最后一页比较,即total_page
            if self.current_page >= self.total_page:
                next_page = '<li class="disabled"><a><下一页></a></li>'
            else:
                self.query_params['page'] = self.current_page + 1
                next_page = '<li><a href="{}?{}"><下一页></a></li>'.format(self.base_url, self.query_params.urlencode())
            html_list.append(next_page)
            # 加上"末页" 功能
            if self.current_page >= self.total_page:
                last = '<li class="disabled"><a>末页</a></li>'
            else:
                self.query_params['page'] = self.total_page
                last = '<li><a href="{}?{}">末页</a></li>'.format(self.base_url, self.query_params.urlencode())
            html_list.append(last)
            html_str = "".join(html_list)  # 拼接成字符串
            result = format_html(html_str)
            return result

     四、django 实现分页下一页序号自增

    在django模板中分页时使用{{forloop.counter }}生成序号时,点击下一页,序号依旧从1开始

    {% for row in user_set%}
        <li>{{forloop.counter}}--{{ row.username }}</li>
    {% endfor %}

    解决办法:views.py向模板发送

         strat=(current_page-1)*count_page

         #current_page为当前页码数,count_page为每页显示数量

     #其实已经在自定义分页写好了,只用拿来发送给模板就可以
    
    render(request,"user_info.html",{"user_set": date,"strat":strat})
    此时模板中的{{forloop.counter }}改为{{forloop.counter|add:strat }}
    
    就可以实现在第二页之后每一页自增

    class ConsultRecordList(BatchOperationMethod):
    
        def get(self, request, *args, customer_id='0', ):
            query_list = ['note']
            q = self.multi_search_conditions(request, query_list)
    
            if customer_id == '0':
                # 规定customer_id =0,拿所有记录
                from django.db.models import Max
                # 获取用户最后的一条记录
                customer_last_record_list = models.ConsultRecord.objects.filter(q, consultant=request.user).values(
                    'customer').annotate(Max('id'))
                consult_record_info_list = []
                for i in customer_last_record_list:
                    # 获取每个客户最后跟进记录的对象
                    recod_obj = models.ConsultRecord.objects.filter(id=i['id__max']).first()
                    consult_record_info_list.append(recod_obj)
            else:
                consult_record_info_list = models.ConsultRecord.objects.filter(
                    q, consultant=request.user,
                    customer_id=customer_id
                ).order_by('-date')
    
            # 添加
            add_btn, next_url = self.get_add_btn(request, reverse('consult_record_add'))
    
            # 分页
            page_obj = Pagination(request,
                                  reverse('consult_record', args=(customer_id,)),
                                  len(consult_record_info_list), settings.PAGE_MAX_SHOW, settings.PAGE_NUM
                                  )
    
            return render(request, 'customer/consult_records.html',
                          {'consult_record_info_list': consult_record_info_list[page_obj.start:page_obj.end],
                           'html_str': page_obj.html_str,
                           'total_page': page_obj.total_page,
                           'start': page_obj.start,
                           'add_btn': add_btn,
                           'next_url': next_url}
                          )
    views.py让序号翻页自增
  • 相关阅读:
    Perl如何安装新模块/包
    Perl入门(二)Perl的流程控制
    Perl入门(一)Perl的基本类型及运算符
    Struts2表单数据接收方式
    Struts2 自定义拦截器时Action无法接收到参数
    深入理解Java闭包概念
    Centos 7.2 Jenkins+Ansible+Gitlab 部署maven项目
    Centos 7.2 Jenkins+Ansible+Gitlab 基础配置
    CentOS 7.2 搭建Jenkins
    Linux系统上安装配置MAVEN
  • 原文地址:https://www.cnblogs.com/sunxiuwen/p/9750316.html
Copyright © 2020-2023  润新知