分页:Paginator

news/2024/11/18 13:36:41/文章来源:https://www.cnblogs.com/zycai/p/18349418

提要:列表分页主要是明白:列表当前需要显示内容索引 =(列表当前页数-1)*每页显示条数   至  列表当前页数*每页显示条数

一、Django的内置分页
Django内置的分页需要使用到3个类:Paginator、EmptyPage、PageNotAnInteger

1.1 Paginator介绍
paginator = Paginator(全部数据, 每页显示条数)

paginator对象下面包括属性per_page、count、num_pages、page对象;

page对象下面包括属性:

has_next、next_page_number、has_previous、previous_page_number、number、object_list、paginator对象

下图为各个对象属性的关系及注释:

1.2  EmptyPage、PageNotAnInteger介绍
EmptyPage、PageNotAnInteger这两个类是为了防止p值(当前页码)不是int类型、或者大于总页码的情况;

1.3  简单截取实例
下面简单截取部分代码诠释:

……
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
def……下面为函数的函数体:
#数据库数据
stu_list=models.Student.objects.all()
cls_list=models.Classes.objects.all()#分页
current_page = request.GET.get('p') #从请求连接中get参数中获取p值,即:当前页码;
所以分页的请求需包含p参数,如:href="/students?p={{ posts.previous_page_number }}"
current_page = int(current_page)
#
paginator = Paginator(stu_list, 10)# 全部数据# per_page:每页显示条目数量# count:数据总个数# num_pages:总页数# page_range:总页数的索引范围# page:page对象(封装了几个属性:是否具有下一页;是否具有上一页;以及下一页/下一页的页码)
try:#page对象posts = paginator.page(current_page)#has_next    是否有下一页#next_page_number    下一页页码#has_previous    是否有上一页#previous_page_number  上一页页码#object_list      分页之后的数据列表,已经切片好的数据#number     当前页#paginator          paginator对象except PageNotAnInteger:posts = paginator.page(1)
except EmptyPage:posts = paginator.page(paginator.num_pages)#pages对象包含了全部的分页需要使用到的属性,包括paginator对象,所以只需将其传入html文件即可;
return render(request,"students.html",{"cls_list":cls_list,"posts":posts})

html文件:

在对应html下include导入pager.html,页面显示:

二、扩展Django内置分页
2.1 继承Paginator类
扩展Django内置分页,主要继承Paginator类,传入参数:current_page(当前页码)、per_pager_num(自定制每页显示页码个数);

之后在对应函数中实例化就只需调用子类CustomerPaginator,传入4个参数:current_page、per_pager_num、全部数据、每页显示条数;

from django.core.paginator import Paginator,EmptyPage,PageNotAnIntegerclass CustomerPaginator(Paginator):'''继承Paginator类,用于保留原有功能、并扩展新的功能'''def __init__(self,current_page,per_pager_num,*args,**kwargs):super(CustomerPaginator,self).__init__(*args,**kwargs)self.current_page = int(current_page) #当前页码self.per_page_num = int(per_pager_num) #分页自定制显示最多页码个数def pager_num_range(self):'''CustomerPaginator自定制新功能:显示分页页码:return:'''if self.num_pages < self.per_page_num:#当数据的总页码数<自定制的每页显示分页页码数时,显示:1到总页码数return range(1,self.num_pages+1)#自定制每页显示页码数/2,取整,主要是想当前页码显示在页码中央:part = int(self.per_page_num/2)if self.current_page <= part:#如果当前页码小于自定制每页显示页码数的一半return range(1, self.per_page_num + 1)if self.current_page + part > self.num_pages:# 如果当前页码加上自定制每页显示页码数的一半,大于总页码数:return range(self.num_pages - self.per_page_num + 1,self.num_pages + 1)#在上面的极端值情况后,常规情况是取当前页前后-+part范围return range(self.current_page - part, self.current_page + part + 1)def students(request):'''学生页面:param request::return:'''stu_list=models.Student.objects.all()cls_list=models.Classes.objects.all()#分页current_page = request.GET.get('p')current_page = int(current_page)#    
#由于上面使用CustomerPaginator继承了Paginator,所以这里使用CustomerPaginator实例化,传入4个参数:当前页码、每页显示页码个数、全部数据、每页显示数据条数paginator = CustomerPaginator(current_page,11,stu_list, 10)try:#page对象posts = paginator.page(current_page)except PageNotAnInteger:posts = paginator.page(1)except EmptyPage:posts = paginator.page(paginator.num_pages)return render(request,"students.html",{"cls_list":cls_list,"posts":posts})

2.2 前端HTML调用

<ul class="pagination" style="margin-top: 0px"><li> <a href="/students.html?p=1" aria-label="F"><span aria-hidden="true">首页</span></a></li>{% if posts.has_previous %}<li> <a href="/students.html?p={{ posts.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li>{% else %}<li> <a href="#" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li>{% endif %}{% for i in posts.paginator.pager_num_range %}{% if i == posts.number %}<li> <a style="background-color: #9acfea;" href="/students.html?p={{ i }}">{{ i }}</a></li>{% else %}<li><a href="/students.html?p={{ i }}">{{ i }}</a></li>{% endif %}{% endfor %}{% if posts.has_next %}<li><a href="/students.html?p={{ posts.next_page_number }}" aria-label="Next"><span aria-hidden="true">下一页</span></a></li>{% else %}<li><a href="#" aria-label="Next"><span aria-hidden="true">下一页</span></a></li>{% endif %}<li> <a href="/students.html?p={{ posts.paginator.num_pages }}" aria-label="Last"><span aria-hidden="true">尾页</span></a></li>
</ul>

三、自定义分页组件
从上面的代码可以看出有两个未解的问题:

1.前端分页的html中的a标签的href链接没有参数化、动态化;还不能百分之百实现别人拿来少部分修改就可以使用;所以,下面自己封装一个类(分页组件);

2.分页类中对象包含了查询的所有数据,万一数据有很多,这样会很浪费性能(针对别的框架哈,django框架不会,因为django是你什么时候需要数据,它才执行)但是还是需要解决;

分页组件代码及部分注释:

 

class Pagination(object):'''自己封装分页组件,别人拿来就可以使用的,需要条件bootstrap、js、若非bootstrap(如layui)请自行修改标签的class属性'''def __init__(self,totalCount,currentPage,modelsName,perPageItrmNum= 10,maxPageNum= 7):'''初始化,传入5个参数:param totalCount: 数据总条数:param currentPage: 当前页:param modelsName: 页码所属模块名,关联url,例举:href='/%s.html?p=%s'%(self.models_name,1)>:param perPageItrmNum: 每页显示条数,默认值10:param maxPageNum: 最多显示页码个数,默认值7'''self.total_count=totalCount#下面这个对current_page当前页码的初始化使用try,是为了防止current_page不是int类型值或小于1,否则赋值=1try:pagenum=int(currentPage)if pagenum<=0:pagenum=1self.current_page = pagenumexcept EmptyPage as e:self.current_page = 1self.models_name=modelsNameself.per_page_item_num = perPageItrmNumself.max_page_num = maxPageNum@propertydef start(self):'''需要显示的数据的起始索引:return: (当前页-1)* 每页显示条数'''return (self.current_page-1)*self.per_page_item_num@propertydef end(self):'''需要显示的数据的最后索引:return:当前页 * 每页显示条数'''return self.current_page * self.per_page_item_num@propertydef num_pages(self):'''总页数:return:'''#divmod(x,y),返回x/y的商a,余数ba,b=divmod(self.total_count,self.per_page_item_num)if b==0:return areturn a+1@propertydef pager_num_range(self):'''Pagination自定制新功能:显示分页页码:return:'''if self.num_pages < self.max_page_num:#当数据的总页码数<自定制的每页显示分页页码数时,显示:1到总页码数return range(1,self.num_pages+1)#自定制每页显示页码数/2,取整,主要是想当前页码显示在页码中央:part = int(self.max_page_num/2)if self.current_page <= part:#如果当前页码小于自定制每页显示页码数的一半return range(1, self.max_page_num + 1)if self.current_page + part > self.num_pages:# 如果当前页码加上自定制每页显示页码数的一半,大于总页码数:return range(self.num_pages - self.max_page_num + 1,self.num_pages + 1)#在上面的极端值情况后,常规情况是取当前页前后-+part范围return range(self.current_page - part, self.current_page + part + 1)@propertydef page_str_ui(self):'''将分页html拼接string,前端html直接调用,渲染:return:'''page_list = []#ul标签开头page_list.append("<ul class='pagination pagination-sm' style='margin-top: 0px'>")#首页temp_first = "<li> <a href='/%s.html?p=1' aria-label='F'>" \"<span aria-hidden='true'>首页</span></a></li>"%(self.models_name)page_list.append(temp_first)#上一页if self.current_page == 1:prev="<li> <a href='#'>" \"<span aria-hidden='true'>上一页</span></a></li>"else:prev="<li> <a href='/%s.html?p=%s'>" \"<span aria-hidden='true'>上一页</span></a></li>"%(self.models_name,self.current_page-1,)page_list.append(prev)#中间页码for i in self.pager_num_range:if i == self.current_page:temp="<li> <a style='background-color: #9acfea;' href='/%s.html?p=%s'>" \"<span aria-hidden='true'>%s</span></a></li>"%(self.models_name,i,i)else:temp = "<li> <a href='/%s.html?p=%s'>" \"<span aria-hidden='true'>%s</span></a></li>" % (self.models_name, i, i)page_list.append(temp)#下一页if self.current_page == self.num_pages:nex="<li> <a href='#'>" \"<span aria-hidden='true'>下一页</span></a></li>"else:nex="<li> <a href='/%s.html?p=%s'>" \"<span aria-hidden='true'>下一页</span></a></li>"%(self.models_name,self.current_page+1,)page_list.append(nex)#尾页temp_last = "<li> <a href='/%s.html?p=%s' aria-label='L'>" \"<span aria-hidden='true'>尾页</span></a></li>"%(self.models_name,self.num_pages)page_list.append(temp_last)#ul结尾page_list.append("</ul>")return "".join(page_list)

使用该分页组件实例截图:

显示结果截图:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/779844.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安规测试-接地电阻测试

一、什么是接地阻抗 接地阻抗是描述电流由接地装置流入带保护外壳处,再流到大地所遇到的阻值,它包括了设备的接地金属外壳、接地线和接地体本身。 二、接地阻抗测试的主要目的 为确定被测物在故障的情况之下,安全接地线是否能承担故障电流的流量,接地的电阻值必须越低越好。…

Xcode 16 beta 5 (16A5221g) 发布 - Apple 平台 IDE

Xcode 16 beta 5 (16A5221g) 发布 - Apple 平台 IDEXcode 16 beta 5 (16A5221g) 发布 - Apple 平台 IDE IDE for iOS/iPadOS/macOS/watchOS/tvOS/visonOS 请访问原文链接:https://sysin.org/blog/apple-xcode-16/,查看最新版。原创作品,转载请保留出处。Xcode 16 的新功能 使…

macOS Sequoia 15 beta 5 (24A5309e) ISO、IPSW、PKG 下载

macOS Sequoia 15 beta 5 (24A5309e) ISO、IPSW、PKG 下载macOS Sequoia 15 beta 5 (24A5309e) ISO、IPSW、PKG 下载 iPhone 镜像、Safari 浏览器重大更新、备受瞩目的游戏和 Apple Intelligence 等众多全新功能令 Mac 使用体验再升级 请访问原文链接:https://sysin.org/blog/…

Web3图谱

备份一下,越来越强。web3学习路线图 web3图谱 BTC图谱 EVM图谱 Solana图谱 Move图谱 ZKP图谱

九龙城寨之围城普通话版粤语版免费在线观看及下载(无广告不卡顿)

本内容只适用于移动用户,联通电信用户就不用浪费时间看下去了哦。 如果你是个急性子,没耐性看太多字,可以直接点击链接观看九龙城寨之围城: https://caiyun.139.com/m/i?005CcstYXSv9D 按照提示就可以在线观看普通话版和粤语版,保真,也可以转存(可下载)。 有耐性看完的…

Task2 - IDA学习【进度 - 第二课】

学习目标: - 无名侠的课,看二进制培训(第二集和第三集)(https://space.bilibili.com/7761039/video)- 会反汇编- 会字符串搜索(f12)- 会简单异或解密了解一下操作系统linux系统的可执行文件的后缀windows系统的可执行文件的后缀了解安装die(Detect It Easy)工具(自行网上…

医疗器械产品分类

一、按照风险程度分类 医疗器械按照风险程度由低到高,管理类别依次分为第一类、第二类和第三类。 医疗器械风险程度,应当根据医疗器械的预期目的,通过结构特征、使用形式、使用状态、是否接触人体等因素综合判定1.第一类医疗器械是风险程度低,实行常规管理可以保证其安全、…

英智AI工程造价解决方案:英智AI造价师

在科技日新月异的今天,人工智能(AI)技术已悄然渗透至各行各业,面对传统而复杂的工程造价领域,AI造价师的诞生,不仅是技术进步的象征,更是对传统造价工程师工作模式的一次深刻变革。面对这一趋势,造价工程师们应当积极应对,让AI成为工作中的得力助手。 英智智能宝是什…

揭秘CentosChina爬虫项目:掌握Scrapy框架的必备技巧与数据库设计

你是否想深入了解如何使用Scrapy框架进行高效爬虫开发?本文将揭秘CentosChina爬虫项目,从项目需求分析、数据库表设计,到Scrapy框架的实用技巧,全方位解析。无论你是初学者还是资深开发者,这篇文章都将为你提供宝贵的经验与指导,助你在爬虫开发领域更上一层楼。Centoschi…

harbor私有镜像仓库高可用部署

Harbor介绍 harbor是一个docker私有镜像仓库,虽然docker官方提供了公共的镜像仓库(Docker Hub),但是从安全和效率等方面考虑,部署私有环境内的Registry也是非常必要的。Harbor是由VMware公司开源的企业级的Docker Registry管理项目。 Harbor的优势: 图形管理界面。 按项目…

面试官:说说MySQL调优?

MySQL 作为关系型数据库的典型代表,其流行程度超越于任何数据库,因此在 Java 面试中,MySQL 是一定会被问到的重要知识点。而在 MySQL 中有一道极其常见的面试题,我们这里系统的来看一下,这就是我们今天要讨论的 MySQL 调优问题。 MySQL 调优的大体思路如下:具体调优思路如…

Thread、ThreadPool、Task之间的联系

1、ThreadPool线程池 一个应用程序最多只能有一个线程池。线程池是一种多线程处理形式,通过QueueUserWorkItem()将任务添加到队列中,然后创建线程(后台线程,又称工作者线程)自动启动这些任务来处理。其中,最小线程数即核心线程数(corePoolSize)是线程池中长期保持的线程…