Django笔记三十四之分页操作

yizhihongxing

本文首发于公众号:Hunter后端

原文链接:Django笔记三十四之分页操作

这一篇笔记介绍一下如何在 Django 使用分页。

Django 自带一个分页的模块:

from django.core.paginator import Paginator

主要用途是列表数据的切割,比如说有 3000 条用户数据,前端需要一个列表接口用于展示这些数据,但是一次性展现这么多数据不合适,所以打算用分页的方式来操作。

比如一页20条数据,前端通过按钮控制 page_num 和 size 参数用于后端返回数据。

以下是本篇笔记目录:

  1. 直接分页操作
  2. Paginator 分页操作
  3. Paginator 其他函数
  4. 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]

如果想获取更多后端相关文章,可扫码关注阅读:
image

原文链接:https://www.cnblogs.com/hunterxiong/p/17364803.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Django笔记三十四之分页操作 - Python技术站

(0)
上一篇 2023年4月30日
下一篇 2023年4月30日

相关文章

  • 【manim动画教程】–高级动画效果

    在常用的动画效果中,介绍了一些元素的创建,销毁,移动和变换的方法,这些方法都是针对单个动画的。如果需要多个动画互相关联,或者元素需要有更复杂的运动方式,那么,仅仅依靠常用的动画效果可能就无法满足要求了。 本篇的高级动画效果主要介绍一些更加灵活的元素运动方式,如何组合多个动画,以及如何联动多个动画的方式。掌握了这些方法,就能够表达出更加复杂的数学几何动画。 1…

    python 2023年4月17日
    00
  • Python中的匿名函数使用简介

    当我们在使用Python编程时,有时候我们只需要定义一个简单的函数,这个函数可能只会被使用一次,那么此时使用匿名函数就显得非常方便。 什么是匿名函数 在Python中,匿名函数也被称为lambda函数,是一种临时的,只能在一处使用的函数,通常用于需要一个函数,但是又不想特意为之创建一个函数的情况。 匿名函数的语法形式如下: lambda args: expr…

    python 2023年6月5日
    00
  • 一篇文章带你详细了解python中一些好用的库

    当谈到Python编程的好处时,经常会被提起的一个主要优势是其庞大的库和工具生态系统。在Python中,拥有成千上万的库,这些库可以快速帮助您解决各种各样的问题并简化您的工作流程。这篇文章将介绍一些好用的Python库,让您了解到这些库的功能和用法,然后在实践中应用它们。 一、Pandas Pandas是一种强大的数据处理库,广泛用于对数据进行分析和操作。P…

    python 2023年6月3日
    00
  • python程序需要编译吗

    Python是一门解释型语言,是不需要编译的,也就是说Python源码无需经过编译器的处理,可以直接运行。这点和Java、C++等编译型语言不同。 Python解释器读取 Python 代码,将其解释成字节码(bytecode),再运行。在这个过程中,Python解释器把代码翻译成一种叫做“字节码”的形式。字节码文件以.pyc为后缀,保存在 pycache …

    python 2023年5月23日
    00
  • python爬虫开发之urllib模块详细使用方法与实例全解

    Python爬虫开发之urllib模块详细使用方法与实例全解 一、概述 在Python的爬虫开发中,网络请求库是必不可少的,而urllib模块就是Python的标准库中较为常用的网络请求库之一。本篇文章将详细介绍urllib模块的使用方法和实例。 二、urllib模块的介绍 urllib模块是Python中一个用于处理网络请求的标准库,包含了四个子模块:ur…

    python 2023年6月3日
    00
  • vue 事件获取当前组件的属性方式

    获取当前组件的属性是Vue组件中经常需要用到的操作。下面是完整的攻略过程: 在Vue组件内部定义事件处理函数,事件处理函数有一个默认的参数,称为事件对象,它包含了当前的Vue实例对象。 通过事件对象可以获取到该组件的属性,属性在Vue组件中存储在$this对象中。 使用$this对象可访问到Vue组件的属性和方法。其中,属性可用于显示数据,方法可用于业务逻辑…

    python 2023年6月13日
    00
  • python利用百度AI实现文字识别功能

    Python利用百度AI实现文字识别功能 前言 百度AI开放平台提供了多种类型的API,其中文字识别API是非常实用的一种,它可以将多种形式的文字图片转换成文本,便于后续处理。本文将介绍如何使用百度AI实现Python文字识别功能。 准备工作 登录百度AI开放平台,创建自己的应用,获取APP_ID、API_KEY、SECRET_KEY信息; 安装Python…

    python 2023年5月18日
    00
  • PyQt5实现QLineEdit正则表达式输入验证器

    以下是PyQt5实现QLineEdit正则表达式输入验证器的完整攻略: 步骤1:安装PyQt5库 在使用PyQt5实现QLineEdit正则表达式输入验证器之前,需要安装PyQt5库。以下是一个示例代码: pip install PyQt5 在这个例子中,我们使用pip命令安装了PyQt5库。 步骤2:创建QLineEdit对象 在使用PyQt5实现QLin…

    python 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部