python测试开发django-115.Paginator分页器展示table表格数据
前言
django自带的分页器Paginator,可以实现分页
Paginator 分页器
paginator模块有3个跟分页相关的类
Paginator:
分页器对象
PageNotAnInteger:
页码不是一个整数时引发该异常
EmptyPage:
页码不在有效范围时(即数据为空)引发该异常
导入Paginator类,可以看到一些内置属性
from django.core.paginator import Paginator
class Paginator:
def __init__(self, object_list, per_page, orphans=0,
allow_empty_first_page=True):
self.object_list = object_list
self._check_object_list_is_ordered()
self.per_page = int(per_page)
self.orphans = int(orphans)
self.allow_empty_first_page = allow_empty_first_page
Paginator 实例化的时候需要传的几个参数
object_list 查询到的对象list
per_page 每页显示的内容
orphans=0, 如果最后一页的数据小于这个值,会合并到上一页
allow_empty_first_page=True, 允许首页为空 ,默认为True
分页器常用的方法
Paginator类实例化后几个常用的属性和方法
p.count 获取数据总量
p.num_pages 获取总页数,如:
23条数据,每页显示5条,总共5页
p.page_range 页面对象可迭代范围
p.page(1) 传数字,获取对应页的数据
MyDjango>python manage.py shell
>>> from yoyo.models import Teacher
>>> all = Teacher.objects.all()
>>> from django.core.paginator import Paginator
# 实例化,每页显示5条数据
>>> p=Paginator(all,per_page=5)
# 获取全部数据 23条
>>> p.count
23
# 获取总页数,23条数据,每页显示5条,总共5页
>>> p.num_pages
5
# 页面对象可迭代范围1-5
>>> p.page_range
range(1, 6)
# 获取第一页的数据
>>> p.page(1)
<Page 1 of 5>
# 如果页数不在1-5范围,抛异常:EmptyPage
>>> p.page(0)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "E:\python36\lib\site-packages\django\core\paginator.py", line 65, in page
number = self.validate_number(number)
File "E:\python36\lib\site-packages\django\core\paginator.py", line 42, in validate_number
raise EmptyPage(_('That page number is less than 1'))
django.core.paginator.EmptyPage: That page number is less than 1
# 如果传入的不是数字类型,会抛异常:PageNotAnInteger
>>> p.page('a')
Traceback (most recent call last):
File "E:\python36\lib\site-packages\django\core\paginator.py", line 38, in validate_number
number = int(number)
ValueError: invalid literal for int() with base 10: 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "E:\python36\lib\site-packages\django\core\paginator.py", line 65, in page
number = self.validate_number(number)
File "E:\python36\lib\site-packages\django\core\paginator.py", line 40, in validate_number
raise PageNotAnInteger(_('That page number is not an integer'))
django.core.paginator.PageNotAnInteger: That page number is not an integer
page()传数字类型后返回一个Page类的实例,可以有以下方法
number 返回当前操作的是第几页
object_list 当前页的操作元素列表
has_next() 判断是否有下一页,返回True或False
has_previous() 判断是否有上一页,返回True或False
has_other_pages() 如果有上一页或下一页,返回True。
previous_page_number() 上一页的页码
next_page_number() 下一页的页码
start_index() 返回当前页上的第一个对象,相对于分页列表的所有对象的序号,从1开始。
比如,将23个对象的列表分为每页5个对象,第2页的start_index()会返回 6。
end_index() 返回当前页上的最后一个对象,相对于分页列表的所有对象的序号,从1开始。
比如,将23个对象的列表分为每页5个对象,第二页的end_index() 会返回 10
>>> page1=p.page(1)
# 返回当前页的对象
>>> page1
<Page 1 of 5>
>>> page1.number
1
>>> page1.has_next()
True
>>> page1.has_previous()
False
>>> page1.start_index()
1
>>> page1.end_index()
5
bootstrap 分页 pagination
bootstrap 分页功能可以看菜鸟教程https://www.runoob.com/bootstrap/bootstrap-pagination.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bootstrap 实例 - 分页的状态</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<ul class="pagination">
<li><a href="#">上一页</a></li>
<li class="active"><a href="#">1</a></li>
<li class="disabled"><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li><a href="#">下一页</a></li>
</ul>
</body>
</html>
如下图左边是pagination分页代码,右边是实现效果,可以在线调试,非常方便
django 视图函数
django 视图函数使用分页器Paginator,根据页面url上的请求参数page来获取当前是第几页。
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
def teachersView(request):
teachers = Teacher.objects.all()
# 分页,每页5个数据
pa = Paginator(teachers, per_page=5)
# 获取页数, 如果无默认返回第一页
page_num = request.GET.get('page', 1)
# 判断传入的page_num是不是合法数字类型
try:
page_num = int(page_num)
page_object = pa.get_page(page_num)
except:
page_object = pa.get_page(1)
return render(request, 'teacher.html', locals())
把pa,page_num,page_object三个参数给到模板
上面代码中的get_page() 方法封装了.page()方法当数字超出page_range页码范围时候的异常处理,大于页码或小于页码都返回最后一页
def get_page(self, number):
"""
Return a valid page, even if the page argument isn't a number or isn't
in range.
"""
try:
number = self.validate_number(number)
except PageNotAnInteger:
number = 1
except EmptyPage:
number = self.num_pages
return self.page(number)
模板实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bootstrap 实例 - 分页的状态</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h3>分页器加载table表格</h3>
<table class="table table-striped">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>电话</th>
</tr>
</thead>
<tbody>
{% for field in page_object %}
<tr>
<td>{{ field.name }}</td>
<td>{{ field.age }}</td>
<td>{{ field.tel }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<ul class="pagination pull-right" id="pager">
{#上一页按钮开始#}
{# 如果当前页有上一页#}
{% if page_object.has_previous %}
{# 当前页的上一页按钮正常使用#}
<li class="previous"><a href="/teachers?page={{ page_object.previous_page_number }}">上一页</a></li>
{% else %}
{# 当前页的不存在上一页时,上一页的按钮不可用#}
<li class="previous disabled"><a href="#">上一页</a></li>
{% endif %}
{#上一页按钮结束#}
{# 页码开始#}
{% for num in pa.page_range %}
{% if num == page_num %}
<li class="active"><a href="/teachers?page={{ num }}">{{ num }}</a></li>
{% else %}
<li><a href="/teachers?page={{ num }}">{{ num }}</a></li>
{% endif %}
{% endfor %}
{#页码结束#}
{# 下一页按钮开始#}
{% if page_object.has_next %}
<li class="next"><a href="/teachers?page={{ page_object.next_page_number }}">下一页</a></li>
{% else %}
<li class="next disabled"><a href="#">下一页</a></li>
{% endif %}
{# 下一页按钮结束#}
</ul>
</div>
</body>
</html>
实现效果图
当页数比较多的时候,中间可以用省略号显示,实现效果如下
具体实现方式,参考下一篇https://www.cnblogs.com/yoyoketang/p/15237570.html