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:python36libsite-packagesdjangocorepaginator.py", line 65, in page
    number = self.validate_number(number)
  File "E:python36libsite-packagesdjangocorepaginator.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:python36libsite-packagesdjangocorepaginator.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:python36libsite-packagesdjangocorepaginator.py", line 65, in page
    number = self.validate_number(number)
  File "E:python36libsite-packagesdjangocorepaginator.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

原文地址:https://www.cnblogs.com/yoyoketang/p/15236252.html