Django笔记三十四之分页操作
本文首发于公众号:Hunter后端
原文链接:Django笔记三十四之分页操作
这一篇笔记介绍一下如何在 Django 使用分页。
Django 自带一个分页的模块:
from django.core.paginator import Paginator
主要用途是列表数据的切割,比如说有 3000 条用户数据,前端需要一个列表接口用于展示这些数据,但是一次性展现这么多数据不合适,所以打算用分页的方式来操作。
比如一页20条数据,前端通过按钮控制 page_num 和 size 参数用于后端返回数据。
以下是本篇笔记目录:
- 直接分页操作
- Paginator 分页操作
- Paginator 其他函数
- Page 的其他操作
1、直接分页操作
在介绍 Django 的分页模块前,我们一般如果要分页的话会如何操作呢,这里我们定义 page_num 参数为 页数,size 参数为一页返回的数据量。
假设有这样一个长度为 20 的列表:
data_list = list(range(20))
我们想要实现每页三条数据,也就是 size = 3,我们根据 page_num 和 size 参数可以这样操作:
target_list = data_list[(page_num - 1) * size: page_num * size]
因为页数是从 1 开始的,而列表的下标是从 0 开始的,所以这里是 page_num - 1。
以这个为例,我们接下来介绍一下如何使用 Django 的模块来操作分页。
2、Paginator 分页操作
Paginator 不仅可以用于 model 的 queryset 数据,也可以用于我们上面这种列表数据 data_list,我们这里使用 data_list 作为示例。
以下是一个简单的使用 Paginator 的示例:
from django.core.paginator import Paginator
data_list = list(range(20))
page_num = 1
size = 3
paginator = Paginator(data_list, size)
target_page_data = paginator.page(page_num)
# <Page 1 of 7>
for item in target_page_data:
print(item)
count = paginator.count
在上面的示例中,Paginator() 方法接收需要分页的可迭代数据,可以是这里的列表,也可以是 Django 里的 QuerySet 类型,然后通过 .page() 函数指定 page_num 数就可以获取指定页数的数据。
另外,如果需要获取总数,可以直接 .count 获取接收的可迭代数据的总数。
分页超出总页数
比如前面我们根据 size 大小对数据进行了分页,最多只能分为 7 页,但是后面我们的 page 数传入的是 7,会怎么办呢?会报错:
raise EmptyPage(_('That page contains no results'))
django.core.paginator.EmptyPage: That page contains no results
如何规避这种情况呢,当然,前端在传入的时候可以做一定的限制,但是后端也要有这样的控制,可以在传入 page_num 参数前就对数据做一个校验,发现 page_num 超出总页数则直接 raise 报错返回前端,或者直接传入 page_num,通过 try except 来控制,发现报错的话,直接返回空列表,比如:
data_list = list(range(20))
page_num = 10
size = 3
paginator = Paginator(data_list, size)
try:
target_page_data = paginator.page(page_num)
except:
target_page_data = []
count = paginator.count
3、Paginator 其他函数
get_page(number)
前面我们对于每页数据的获取有一个 try except 的操作:
try:
target_page_data = paginator.page(page_num)
except:
target_page_data = []
假设说我们的数据只能分 7 页数据,那么 paginator.page(page_num) 的 page_num 参数就只能在 1-7 之间,可以是 int,也可以是字符串的 1-7,比如 "2",除此之外输入的其他参数,比如 0, -1,或者其他非法字符串都会引发报错。
所以我们使用了一个 try except 操作来捕获异常,当发生异常时,我们返回的是空列表。
get_page() 函数相当于是基于 page() 函数做了异常处理,当我们输入的数据是非法整数时,比如页数在 1-7 之间,我们输入的是 0,或者 -1,或者 10,返回的则是最后一页数据:
>>> paginator.get_page(99)
<Page 7 of 7>
如果我们输入的是其他的非法数据的时候,返回的则是第一页数据:
>>> paginator.get_page('a')
<Page 1 of 7>
count 属性
前面介绍了,可以通过 paginator.count 的方式来拿到待分页的数据的总数,这里介绍一下 .count 实现的方式。
因为 Paginator 是既可以对列表类型数据进行分页,也可以对 QuerySet 进行分页,但是 QuerySet 有 .count() 函数,而列表数据是没有这个操作的。
但是如果统一都用 len() 函数来对输入的数据进行取长度,这又是不现实的,因为 len() 函数的操作流程会将 QuerySet 数据都加载然后取值,在 QuerySet 无比大的时候这又是不现实的,这一点在之前的 Django 查询优化笔记中有记录。
所以这里的 count 背后的方法是先去查看这个数据有没有 count() 方法,有的话就执行,比如一个 QuerySet,没有的话就执行 len() 函数,比如列表数据。
num_pages 属性
返回总页数,比如我们前面的示例返回的数据是 7:
paginator.num_pages
# 7
page_range 属性
返回页数范围,是一个 range() 类型:
paginator.page_range
4、Page 的其他操作
这里的 Page 指的是分页后的一页数据的 Page 类型,也就是前面我们定义的 target_page_data 数据:
target_page_data = paginator.page(page_num)
是否有前一页
>>> target_page_data.has_previous()
# True
是否有后一页
>>> target_page_data.has_next()
# True
获取下一页的页数
>>> target_page_data.next_page_number()
# 2
获取前一页的页数
target_page_data.next_page_number()
注意:如果当前页在第一页或者最后一页,当我们使用获取前一页或者下一页的页数时会报错。
当前页的开始和结束索引
对于某页数据,如果想获取该页数据在全部数据中的索引,比如说,对于一个长度为 20 的列表进行分页,每页数量为 4,获取的是第 1 页的数据,那么这页数据的开始和结束索引就在 1 和 4,因为这里定义的索引是从 1 开始计算的。
>>> target_page_data = paginator.page(1)
>>>
>>> target_page_data.start_index()
# 1
>>> target_page_data.end_index()
# 4
当前页数
获取当前页数:
target_page_data.number
获取当前页数据列表
>>> target_page_data.object_list
[12, 13, 14]
如果想获取更多后端相关文章,可扫码关注阅读:

Django笔记三十四之分页操作的更多相关文章
- Python笔记(十四):操作excel openpyxl模块
(一) 常遇到的情况 就我自己来说,常遇到的情况可能就下面几种: 读取excel整个sheet页的数据. 读取指定行.列的数据 往一个空白的excel文档写数据 往一个已经有数据的excel文档追加 ...
- 论文阅读笔记三十四:DSSD: Deconvolutiona lSingle Shot Detector(CVPR2017)
论文源址:https://arxiv.org/abs/1701.06659 开源代码:https://github.com/MTCloudVision/mxnet-dssd 摘要 DSSD主要是向目标 ...
- Android笔记三十四.Service综合实例二
综合实例2:client訪问远程Service服务 实现:通过一个button来获取远程Service的状态,并显示在两个文本框中. 思路:如果A应用须要与B应用进行通信,调用B应用中的getName ...
- tensorflow学习笔记(三十四):Saver(保存与加载模型)
Savertensorflow 中的 Saver 对象是用于 参数保存和恢复的.如何使用呢? 这里介绍了一些基本的用法. 官网中给出了这么一个例子: v1 = tf.Variable(..., nam ...
- PHP学习笔记三十四【记录日志】
<?php function my_error2($errno,$errmes) { echo "错误号:".$errno; //默认时区是格林威治相差八个时区 //设置 1 ...
- python学习 (三十四) Python文件操作
1 写文件 my_list = ["] my_file = open("myfile.txt", "w") for item in my_list: ...
- 《手把手教你》系列技巧篇(三十四)-java+ selenium自动化测试-单选和多选按钮操作-中篇(详解教程)
1.简介 今天这一篇宏哥主要是讲解一下,如何使用list容器来遍历单选按钮.大致两部分内容:一部分是宏哥在本地弄的一个小demo,另一部分,宏哥是利用JQueryUI网站里的单选按钮进行实战. 2.d ...
- 如鹏网学习笔记(十四)ASP.NET
Asp.net笔记 一.Socket类 进行网络编程的类,可以在两台计算机之间进行网络通讯 过程: 向服务器发送指令: GET /index.html HTTP/1.1 Host:127.0.0.1: ...
- 孤荷凌寒自学python第四十四天Python操作 数据库之准备工作
孤荷凌寒自学python第四十四天Python操作数据库之准备工作 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天非常激动地开始接触Python的数据库操作的学习了,数据库是系统化设计 ...
- 孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习
孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.close() 当一个file对象执行此方法时,将关闭当前 ...
随机推荐
- Spyglass CDC工具使用(五)
最近一直在搞CDC (clock domain crossing) 方面的事情,现在就CDC的一些知识点进行总结. 做CDC检查使用的是Spyglass工具.以下内容转载自:Spyglass之CDC检 ...
- 阿里云CentOS7 下部属nginx+uwsgi+python3+django
安装依赖包 yum -y groupinstall "Development tools" yum install openssl-devel bzip2-devel expat- ...
- ios装包
一.下载爱思助手 二.找到本机设备 注:如果未弹出允许.拒绝调试选项可尝试换根数据线解决 三.将对应包体文件拖入本机设备
- java获取前端的token并验证与拦截器
请求时获取token并验证 public class MyInterceptor implements HandlerInterceptor { //方法执行前进行拦截 @Override publi ...
- ARP欺骗工具-arpspoof
arpspoof arpspoof是dsniff下的一个ARP欺骗工具 大概原理: 两台主机HostA 和 HostB想要进行通信的流程,那么主机A将需要知道自己的ip,mac 以及主机B的ip, m ...
- Navicat基础教程
1.安装 可以直接前往官网进行安装,网址如下: https://navicat.com.cn/download/navicat-premium 下载之后将下载后的压缩包解压到当前文件夹,然后根据里面自 ...
- .NET应用系统的国际化-基于Roslyn抽取词条、更新代码
上篇文章我们介绍了 VUE+.NET应用系统的国际化-多语言词条服务 系统国际化改造整体设计思路如下: 提供一个工具,识别前后端代码中的中文,形成多语言词条,按语言.界面.模块统一管理多有的多语言词条 ...
- Django-5
Django-5 1.Coookie 1.1 什么是cookie Cookie是储存在浏览器端的一小段文本数据(键值对). 被广泛用于在网站之间传输信息, 当您访问一个网站时,它会将一个Cookie发 ...
- 跨域解决方案CORS
这里说的 js 跨域是指通过 js 在不同的域之间进行数据传输或通信,例如通过 ajax 向一个不同的域请求数据,或者通过 js 获取页面中不同域中(iframe)的数据.只要协议.域名.端口有任何一 ...
- JVM 频繁 FULL GC 快速排查整理
在分享此案例前,先聊聊哪些场景会导致频繁Full GC: 内存泄漏(代码有问题,对象引用没及时释放,导致对象不能及时回收)死循环大对象程序执行了System.gc() 尤其是大对象,80%以上的情况就 ...