- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
本文首发于公众号:Hunter后端 。
原文链接: Django笔记三十四之分页操作 。
这一篇笔记介绍一下如何在 Django 使用分页.
Django 自带一个分页的模块:
from django.core.paginator import Paginator
主要用途是列表数据的切割,比如说有 3000 条用户数据,前端需要一个列表接口用于展示这些数据,但是一次性展现这么多数据不合适,所以打算用分页的方式来操作.
比如一页20条数据,前端通过按钮控制 page_num 和 size 参数用于后端返回数据.
以下是本篇笔记目录:
在介绍 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 的模块来操作分页.
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
前面我们对于每页数据的获取有一个 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>
前面介绍了,可以通过 paginator.count 的方式来拿到待分页的数据的总数,这里介绍一下 .count 实现的方式.
因为 Paginator 是既可以对列表类型数据进行分页,也可以对 QuerySet 进行分页,但是 QuerySet 有 .count() 函数,而列表数据是没有这个操作的.
但是如果统一都用 len() 函数来对输入的数据进行取长度,这又是不现实的,因为 len() 函数的操作流程会将 QuerySet 数据都加载然后取值,在 QuerySet 无比大的时候这又是不现实的,这一点在之前的 Django 查询优化笔记中有记录.
所以这里的 count 背后的方法是先去查看这个数据有没有 count() 方法,有的话就执行,比如一个 QuerySet,没有的话就执行 len() 函数,比如列表数据.
返回总页数,比如我们前面的示例返回的数据是 7:
paginator.num_pages
# 7
返回页数范围,是一个 range() 类型:
paginator.page_range
这里的 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笔记三十四之分页操作的文章就讲到这里了,如果你想了解更多关于Django笔记三十四之分页操作的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我对 Python-Django 和 web 开发还很陌生,我被困在这个使用 POST 创建新资源的特殊问题上。 我正在为 REST API 使用 Django REST 框架,我正在尝试创建一个新资
我已经使用 Django-storages 成功地将 Word 文档存储到 S3。 class Document(TitleSlugDescriptionModel, TimeStampedModel
我有 2 个关于模型代理的问题, 如何从模型对象创建代理对象? 如何从模型查询集创建代理查询集? 例如,假设我们定义了: from django.contrib.auth.models import
我想编写一个直接执行 HTTP 请求的单元测试(而不是使用 django.test.client.Client)。 如果您好奇为什么 - 那是因为我想测试我从 Django 应用程序公开的 Thrif
我为我的个人网站启动了一个 django 项目来学习 django。到目前为止,我已经将我的开发环境设置为我需要的一切,并遵循 this很棒的教程来创建一些基本的数据结构和模板。现在我想开始使用我之前
我已经阅读了很多关于如何在使用 Django 注册时添加额外字段的信息,例如 here 、 here 和 here 。代码片段是: forms.py(来自注册应用程序) class Registrat
我正在编写小型社交应用程序。功能之一是在网站标题中写入用户名。因此,例如,如果我登录并且我的名字是Oleg(用户名),那么我应该看到: Hello, Oleg | Click to edit prof
我有一个使用 Django 和 Django Rest 框架开发的应用程序。我想将 django-reversion 功能添加到我的应用程序中。 我已经尝试过http://django-reversi
我有一个简单的 HTML 表单,我没有使用 Django 表单,但现在我想添加一个选择。 选择最容易创建为 Django ChoiceField (与通过循环等手动创建选择相反),但是,如果没有在 D
我不明白为什么人们以两种方式编写外键,这样做的目的是什么?它们是相同还是不同? 我注意到有些人这样写: author = models.ForeignKey(Author, on_delete=mod
我想在我的 Django 应用程序中获取评论最多的十个帖子,但我做不到,因为我想不出合适的方法。 我目前正在使用 django 评论框架,并且我已经看到使用 aggregate or annotate
这对于 Django 1.2 仍然有效吗? Custom Filter in Django Admin on Django 1.3 or below 我已经尝试过,但管理类中的 list_filter
问题在于,当 django-compressor 编译为 .js 文件的 CoffeeScript 文件中引用 {{ STATIC_URL }} 时,它无法正确加载。 在我的 django 模板中,我
我正在尝试将一些字段从一个 django 模型移动到一个新模型。假设我有一个书籍模型: class Book(models.Model): title = models.CharField(max
我想在我的 Django 应用程序中获取评论最多的十个帖子,但我做不到,因为我想不出合适的方法。 我目前正在使用 django 评论框架,并且我已经看到使用 aggregate or annotate
目前我正在寻找在 Django 中实现访问控制。我已经阅读了有关内置权限的内容,但它并不关心每个对象的基础。例如,我想要“只有创建者可以删除自己的项目”之类的权限。所以我读到了 django-guar
嗨,我正在将我的 Django 模型的一个字段的值设置为其他模型的另一个字段的值。这个值应该是动态变化的。 这是我的第一个模型 class MainModel(AbstractBaseUser, Pe
我正在尝试为我的模型创建一个编辑表单。我没有使用模型表单,因为根据模型类型,用户可以使用不同的表单。 (例如,其中一个表单有 Tinymce 小部件,而另一个没有。) 有没有什么方法可以使用模型设置表
Django 模板中的搜索字段 如何在类似于此图像的 Django 模板中创建搜索字段 http://asciicasts.com/system/photos/1204/original/E354I0
根据 Django documentation ,如果 Django 安装激活了 AuthenticationMiddleware,HttpRequest 对象有一个“user”属性代表当前登录的用户
我是一名优秀的程序员,十分优秀!