Django进阶–分页

本文是一篇学习笔记,在官方文档基础上加以整理而形成。想要查看关键字段官方文档,请点击相应的符号:

1. 简介

关于分页查询我是一个新手,简谈我对手动编写分页查询的感受:首先是对新手的不友好、第一次写一个简单的分页花了一天的时间;其次就是分页归属于查询,所以和查询的逻辑、身份验证以及数据库的操作密不可分,在一个大知识环境里编写代码还是比较容易出错的;还有就是日后修改业务时,阅读代码的艰辛。

因为本人纯属菜鸟,虽然以上问题对于高手可以随手为之,但我走的却是很艰辛。所以决定学习Django官方封装的分页功能pagination,他不能简化逻辑,只是能降低代码量(封装了一些底层方法)。

django版本:2.1.7

数据库:mysql,通过模型建立关系。

2 Pagiantor

2.1 简介

Paginator类是 Django 官方提供的分页管理器。

#实例化
pagi = (object_list, per_page)
  • object_list:任何可迭代对象,list, tuple, str和模型查询返回的QuerySet;
  • per_page:一页几个元素,指定页面大小。

举个栗子

In [1]: from book.models import Student
In [1]: from django.core.paginator import Paginator
    
In [18]: stus = Student.objects.all().order_by('-c_time')  #用QuerySet对象建立分页管理器,必须先排序
In [21]: stus                                        
Out[21]: <QuerySet [
    <Student: id<1>name[新一]gender(男)age|16|c_time:2019-03-20 15:25:09+00:00>, 
    <Student: id<2>name[元太]gender(男)age|16|c_time:2019-03-20 15:26:16+00:00>, 
    <Student: id<23>name[阿飞]gender(男)age|25|c_time:2019-03-26 00:55:50.108942+00:00>
]>
In [22]: pagi = Paginator(stus, 3)
  • 关于模型的相关知识,可以查阅我的:Django模型–数据库(MySQL)-初识
  • pagi 就是一个分页管理器对象我们可以通过它,实现分页。
  • object_list对象必须有 count 或者 _len_ 方法

2.2 属性

1. count

返回object_list的长度,即所有元素的总个数。

# pagi是上个例子中,Student表中所有数据的分页管理器
In [29]: pagi.count             #返回总的记录条数                     
Out[29]: 11
    
In [30]: Student.objects.all().only().count()    #Student表中确实有11条数据    
Out[30]: 11
  • count 属性被调用时,Paginator会先调用object_list.count(),若无该方法、回退使用len(object_list)
  • 对于数据库对象,count方法效率极高(和数据库引擎有关);

2. num_pages

返回总共有多少页

In [31]: pagi.num_pages                              
Out[31]: 4
# pagi.count = 11; per_page = 3; 11 / 3 向上取整得4

3. page_range

返回下标从1开始的页码迭代器,每个元素是页码对应的整数;比如一个分页器将object_list分为三页、则返回: [1, 2, 3]

In [32]: pagi.page_range                             
Out[32]: range(1, 5)
# pagi.num_pages = 4。

3 Page对象

3.1 简介

每个Page对象对应众多页面中的一个。

# Page对象通常不用手工创建
class Page (object_list, number, paginator)

# Page 依于 Paginator,所以通过 Paginator 创建
In [33]: pagi.page(1)                                
Out[33]: <Page 1 of 4>
# 一共有四个页面,这是第一个

3.2 方法

1. has_next

判断是否有下一页,若有、返回True;

In [36]: page1 = pagi.page(1)     #page1 对应第一页                   

In [37]: page1.has_next()                            
Out[37]: True

2. has_previous

判断是否有上一页,若有、返回True;

In [39]: page1.has_previous()                        
Out[39]: False

3. has_other_pages

如果有下一页上一页,返回True;

#创建一个仅包含1页的分页管理器对象。
In [44]: pagn = Paginator('abc', 3)                  

In [45]: pagen1 = pagn.page(1)  
    
In [47]: pagn.num_pages                              
Out[47]: 1

In [49]: pagen1.has_other_pages()                    
Out[49]: False

4. next_page_number

返回下一页编号,如果下一页不存在触发异常InvalidPage(后面会讲到,即页面参数异常,源于页面参数过界)

In [50]: page1.next_page_number()                    
Out[50]: 2

5. previous_page_number

返回上一页编号,如果上一页不存在触发异常InvalidPage

In [52]: page2 = pagi.page(2)                        

In [53]: page2.previous_page_number()                
Out[53]: 1

6. start_index

返回本页第一个元素在objects_list中的编号,注意:编号会从1开始。

# pagi 共有11条记录(元素),每页3条记录,共4页
# page1是第一页,函数返回编号1
In [55]: page1.start_index()                         
Out[55]: 1
# page2是第二页,函数返回编号4(1 * 3 +1 = 4)
In [56]: page2.start_index()                         
Out[56]: 4

6. end_index

返回本页最后一个元素在objects_list中的编号,注意:编号会从1开始。

In [58]: page1.end_index()         #1 * 3                  
Out[58]: 3

In [59]: page2.end_index()         #2 * 3                 
Out[59]: 6

3.2 属性

1. object_list

返回对象列表objects_list

In [60]: pagen1.object_list                          
Out[60]: 'abc'

2. number

返回当前页面编号

In [65]: page1.number                                
Out[65]: 1

In [66]: page2.number                                
Out[66]: 2

3. paginator

返回当前页面所属的分页管理器Paginator对象实例

In [67]: page2.paginator                             
Out[67]: <django.core.paginator.Paginator at 0x7f6a63f33438>

In [68]: page2.paginator.num_pages                   
Out[68]: 4

感谢潭州,一路走来,始终如一;

心蓝老师是最棒的;