当前位置: 首页 > news >正文

Django分页器

Django分页器

一、分页器简介

当数据量非常大时, 我们不可能把所有的数据都放在同一页中, 于是就有了分页的概念, 将数据像书一样每一页规定可容纳多少条数据, 运用到Django中的分页组件, 它其实是Django内置的一个类

二.Paginator对象与Page类对象

1.如何得到这两个类对象

  • 导入分页类
from django.core.paginator import Paginator
  • Paginator类对象
# 语法伪代码
paginator = Paginator([要分页的数据],[每页显示条数])
# 示例
paginator = Paginator(shop_list,10)
  • Page类对象
# 语法伪代码
page = paginator.page([第几页])
# 示例
page = paginator.page(2)  # 获取第二页对象

2.Paginator类对象属性和方法

  • 属性
属性名说明
count返回数据总条数
num_pages返回分页之后的总页数
per_page每页显示的条数
page_range返回分页后页码的列表
  • 方法
方法名说明
page(self, number)返回地number页的page类实例对象

3.Page类对象属性和方法

  • 属性
属性名说明
number返回当前页页码
object_list返回当前页的数据列表
paginator返回对应的Paginator类对象
  • 方法
方法名说明
has_previous( )判断当前页是否有上一页
has_next( )判断当前页是否有下一页
previous_page_number( )返回前一页页码
next_page_number( )返回下一页页码

三.创建表并插入数据(准备工作)

1.创建模型类

class Shop(models.Model):
    name = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    nums = models.IntegerField(verbose_name='商品剩余')

    def __str__(self):
        return self.name

2.使用for循环批量插入数据

for i in range(1,151):
    models.Shop.objects.create(name=f'商品{i}',price=10+int(f'{i}'),nums=f'{random.randint(1,15)}')

每循环一次就连接一次数据库, 效率低

3.bulk_create( ) : 批量插入数据

import random
shop_list = []
for i in range(1,151):
    book = models.Shop(name=f'商品{i}',price=10+int(f'{i}'),nums=f'{random.randint(1,15)}')
    shop_list.append(book)
models.Shop.objects.bulk_create(shop_list,10)  # 第二个参数是每次插入的条数

可以指定每次插入的条数, 效率高

4.将初始数据渲染到页面

  • page_shop.html 文件
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-info">
                <div class="panel-heading text-center">商品信息表</div>
                <div class="panel-body">
                    <table class="table table-striped table-hover">
                        <thead>
                            <tr>
                                <th>编号</th>
                                <th>商品名</th>
                                <th>价格</th>
                                <th>剩余个数</th>
                            </tr>
                        </thead>
                        <tbody>
                            {% for obj in shop_obj %}
                                <tr>
                                    <th>{{ obj.id }}</th>
                                    <th>{{ obj.name }}</th>
                                    <th>{{ obj.price }}</th>
                                    <th>{{ obj.nums }}</th>
                                </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>         
  • 展示效果

img

以上是没有没有分页的效果, 一页翻不到头, 使用起来不方便

四.分页器完整用法

1.实现需求

  • 每页显示15条数据
  • 页码列表只展示11页, 随着当前页变化
  • 当前页为第一页则禁用’‘上一页’'按钮
  • 当前页为最后页则禁用’‘下一页’'按钮
  • 当前页按钮处于激活状态

2.效果展示

  • 整体展示

imgimg

3.代码实现

  • 路由层 urls.py 文件
re_path('^page_shop/', views.page_shop)
  • 视图层 views.py 文件

视图层需要传给前端使用的三个参数(核心) :

  • 分页后的paginator对象,用来展示数据
  • 分页后的页码列表,我们规定每次展示11个页码,中间页码为当前页,左右页码随之变化(这里需要注意前11页和后11页)
  • 收到前端点击的页码,我们要返回该页码(page)对象(注意小于或超出中页码的情况)
from django.shortcuts import render, HttpResponse, redirect
from app01 import models

def page_shop(request):
    # 🔰1.分页后的paginator对象
    current_page = int(request.GET.get('page_num',1))  # 获取用户点击的页码,没有则默认第一页
    shop_list = models.Shop.objects.all()              # 获取所有的商品对象列表
    paginator = Paginator(shop_list,15)                # 每页展示15条商品信息

    # 🔰2.页码列表
    # 如果分页后的总页数大于11
    if paginator.num_pages > 11:
        # 总共11页,取中间页(当前页)来判断是否是第1~11页
        if current_page - 5 < 1:
            # 1~11页码列表
            page_range = range(1, 12)
        # 取11页的中间页(当前页)判断是否是最后11页
        elif current_page + 5 > paginator.num_pages:
            # 最后11页页码列表
            page_range = range(paginator.num_pages - 10, paginator.num_pages + 1)
        else:
            # 如果不是前面11页,也不是后面11页,那么页码列表动态就会随着当前列表动态加减
            page_range = range(current_page - 5, current_page + 5)
    else:
        # 总页数小于11就直接全部显示
        page_range = paginator.page_range

    # 🔰3.page对象
    try:
        # 如果前端传过来的页码小于分页后的最小页码或者大于最大页码就会报错
        page = paginator.page(current_page)
    except Exception as E:
        current_page = 1  # 如果超出或小于我们就让其默认展示第一页
        page = paginator.page(current_page)

    return render(request, 'page.html', {'page_range': page_range, 'page': page, 'current_page': current_page})
  • 模板层 page.html 文件
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-info">
                <div class="panel-heading text-center">商品信息表</div>
                <div class="panel-body">
                    <table class="table table-striped table-hover">
                        <thead>
                            <tr>
                                <th>编号</th>
                                <th>商品名</th>
                                <th>价格</th>
                                <th>剩余个数</th>
                            </tr>
                        </thead>
                        <tbody>
                            {# 展示当前页的所有数据 #}
                            {% for obj in page.object_list %}
                                <tr>
                                    <th>{{ obj.id }}</th>
                                    <th>{{ obj.name }}</th>
                                    <th>{{ obj.price }}</th>
                                    <th>{{ obj.nums }}</th>
                                </tr>
                            {% endfor %}
                        </tbody>
                    </table>
{# -------------------上面为数据渲染,下面为页码列表-------------------- #}                   
                    <div class="text-center">
                        <nav aria-label="Page navigation">
                            <ul class="pagination">
                                {# 判断当前页是否有上一页(针对向左的箭头按钮) #}
                                {% if page.has_previous %}
                                    <li>
                                        {# 如果有上一页就跳到上一页 #}
                                        <a href="/page_shop/?page_num={{ page.previous_page_number }}"
                                           aria-label="Previous">
                                            <span aria-hidden="true">&laquo;</span>
                                        </a>
                                    </li>
                                {% else %}
                                    {# 如果没有上一页,就将该按钮禁用 #}
                                    <li class="disabled">
                                        <a href="" aria-label="Previous">
                                            <span aria-hidden="true">&laquo;</span>
                                        </a>
                                    </li>
                                {% endif %}

                                {# 从页码列表中循环取出页码与当前页做对比 #}
                                {% for foo in page_range %}
                                    {% if current_page == foo %}
                                        {# 如果是当前页,就将当前页按钮变成激活状态(蓝色) #}
                                        <li class="active"><a href="/page_shop/?page_num={{ foo }}">{{ foo }}</a></li>
                                    {% else %}
                                        {# 如果不是则不变色 #}
                                        <li><a href="/page_shop/?page_num={{ foo }}">{{ foo }}</a></li>
                                    {% endif %}

                                {% endfor %}

                                {# 判断但前页是否有下一页(针对向右的箭头按钮) #}
                                {% if page.has_next %}
                                    <li>
                                        {# 如果有则跳转到下一页 #}
                                        <a href="/page_shop/?page_num={{ page.next_page_number }}" aria-label="Next">
                                            <span aria-hidden="true">&raquo;</span>
                                        </a>
                                    </li>
                                {% else %}
                                    {# 没有下一页则将按钮禁用 #}
                                    <li class="disabled">
                                        <a href="" aria-label="Next">
                                            <span aria-hidden="true">&raquo;</span>
                                        </a>
                                    </li>
                                {% endif %}

                            </ul>
                        </nav>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

以上视图层和模板层可以当固定模板来使用, 只需要修改模型类(你的数据)

相关文章:

  • from组件
  • python语法之注释
  • python语法之变量、常量
  • Python基本运算符
  • Python语法入门之垃圾回收机制
  • Python格式化字符串的4种方式
  • Python语法入门之基本数据类型
  • Python语法入门之与用户交互与格式化输出
  • python之数据类型之可变与不可变类型
  • python流程控制之for循环
  • python流程控制之while循环
  • Python语法入门之流程控制if判断
  • IDE集成开发环境的基本使用
  • Python实战演练:ATM + 购物车项目开发
  • 博客搬家通告!
  • 【Linux系统编程】快速查找errno错误码信息
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • Cumulo 的 ClojureScript 模块已经成型
  • JavaScript 基础知识 - 入门篇(一)
  • PHP 的 SAPI 是个什么东西
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Sass 快速入门教程
  • Vue2.0 实现互斥
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 我的zsh配置, 2019最新方案
  • ​configparser --- 配置文件解析器​
  • # C++之functional库用法整理
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • #Linux(make工具和makefile文件以及makefile语法)
  • (31)对象的克隆
  • (区间dp) (经典例题) 石子合并
  • (转)编辑寄语:因为爱心,所以美丽
  • (转)创业家杂志:UCWEB天使第一步
  • .net core 6 集成和使用 mongodb
  • [ solr入门 ] - 利用solrJ进行检索
  • [100天算法】-不同路径 III(day 73)
  • [8-27]正则表达式、扩展表达式以及相关实战
  • [AIGC 大数据基础]hive浅谈
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured
  • [Avalon] Avalon中的Conditional Formatting.
  • [BZOJ1040][P2607][ZJOI2008]骑士[树形DP+基环树]
  • [docker] Docker的数据卷、数据卷容器,容器互联
  • [ERROR] Plugin 'InnoDB' init function returned error
  • [E链表] lc83. 删除排序链表中的重复元素(单链表+模拟)
  • [hdu 4405] Aeroplane chess [概率DP 期望]
  • [IDF]聪明的小羊
  • [IE 技巧] 显示/隐藏IE 的菜单/工具栏
  • [IE技巧] IE 中打开Office文件的设置
  • [LeetCode] 626. 换座位
  • [Linux_IMX6ULL驱动开发]-基础驱动
  • [ndss 2023]确保联邦敏感主题分类免受中毒攻击
  • [python]python os模块 常用命令
  • [SoapUI] SoapUI学习视频地址