django分页功能实现

一、django内置分页模块介绍

django内置的分页功能需要引入内置模块from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

Paginator是一个类,可实例化出一个对象,实例化的对象中封存了以下属性,示例paginator = Paginator(所有数据,每页显示数量)

per_page: 每页显示数量

count: 数据总个数

num_pages:总页数

page_range:总页数的索引范围,如: (1,10),(1,200)

page对象,示例paginator.page(current_page)

而page对象中也封存了以下属性

object_list:分页之后的数据列表,已经切片好的数据

has_next:是否有下一页

next_page_number 下一页页码

has_previous 是否有上一页

previous_page_number 上一页页码

number 当前页

paginator对象

二、扩展django内置分页功能

#生成数据
value_list=[]
for i in range(1,501):
    temp = {'name':'root'+str(i),'age':i}
    value_list.append(temp)

#自定义paginator对象,继承python自带的Paginator对象
class customePaginator(Paginator):
    def __init__(self,current_page,show_page_number,*args,**kwargs):#传入参数为当前页、页面显示的页码数
        self.current_page = int(current_page)
        self.show_page_number = int(show_page_number)
        super().__init__(*args,**kwargs)
    def page_number_range(self):#获取当前页面显示的页码范围
        if self.num_pages < self.show_page_number:  #如果数据总页数小于页面显示页码数,页面显示页码数范围为[1,总页数]
            return range(1,self.num_pages+1)
        part = int(self.show_page_number/2)
        if self.current_page <= part: #如果当前页小于页面显示页码数的一半,页面显示页码数范围为[1,页面显示页码数],即当前页码很小的情况
            return range(1,self.show_page_number+1)
        if (self.current_page+part)>self.num_pages:#如果当前页与页面显示页码数的一半的和大于总页数,页面显示页码数范围为[总页数-页面显示页码数,总页数],即当前页码很大的情况
            return range(self.num_pages-self.show_page_number+1,self.num_pages+1)
        return range(self.current_page-part,self.current_page+part+1)

#url对应的处理函数
def index1(request):
    per_page = 10    #每页显示10条数据
    show_page_number = 11   #页面显示11个页码,建议为奇数
    current_page = int(request.GET.get('p')) #获取当前页
    post = customePaginator(current_page,show_page_number,value_list,per_page)  #实例化自定义的类的对象
    try:  #实例化page对象
        page = post.page(current_page)
    except PageNotAnInteger:  #如果传入的参数不是整数,page为当前页
        page = post.page(1)
    except EmptyPage:  #如果传入参数大于总页数,page为最后一页
        page = post.page(post.num_pages)
    return render(request,'index1.html',{'post':page})
<!--显示页面html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <ul>
        {% for p in post.object_list %}
            <li>{{ p.name }} {{ p.age }}</li>   <!--页面显示内容-->
        {% endfor %}
    </ul>
    {% include 'include/pagecut.html' %}  <!--页码部分,通过include引入-->
</div>
</body>
</html>

<!--页面模板,单独成一个html文件-->
{% if post.has_previous %}
    <a href="index1?p={{ post.previous_page_number }}">上一页</a>
    {% else %}
    <a href="#">上一页</a>
{% endif %}

{% for p in post.paginator.page_number_range %}
    {% if p == post.number %}
         <a href="index1?p={{ p }}" style="font-size: 20px">[{{ p }}]</a>
        {% else %}
         <a href="index1?p={{ p }}" >[{{ p }}]</a>
    {% endif %}
{% endfor %}

{% if post.has_next %}
    <a href="index1?p={{ post.next_page_number }}">下一页</a>
    {% else %}
     <a href="#">下一页</a>
{% endif %}
<span>{{ post.number }}/{{ post.paginator.num_pages }}</span>

三、自定义分页功能

#自定义Pagination对象,模拟django内置Paginator对象
class Pagination(object):
    def __init__(self,totalCount,currentPage,perPage=10,showPageNum=11):#初始化,四个参数分别表示数据总个数、当前页、每页显示个数、页面显示页码数
        self.total_count = totalCount
        try:
            p = int(currentPage)
            if p <= 0:
                p = 1
            self.current_page = p
        except Exception as e:
            self.current_page = 1
        self.per_page = perPage
        self.show_page_num = showPageNum
    
    @property #页面显示数据的起始序列号
    def start(self):  
        return (self.current_page-1) * self.per_page

    @property #页面显示数据的结束序列号
    def end(self):
        return self.current_page * self.per_page

    @property  #数据总页数
    def num_pages(self):
        a,b = divmod(self.total_count,self.per_page)
        if b ==0:
            return a
        return a+1

    def page_number_range(self):  #页面显示页码数的范围
        if self.num_pages < self.show_page_num:
            return range(1,self.num_pages+1)
        part = int(self.show_page_num/2)
        if self.current_page <= part:
            return range(1,self.show_page_num+1)
        if (self.current_page+part)>self.num_pages:
            return range(self.num_pages-self.show_page_num+1,self.num_pages+1)
        return range(self.current_page-part,self.current_page+part+1)

    def page_str(self):   #生成页面显示页码的html串
        page_list = []

        first = "<li><a href='index2?p=1'>首页</a></li>"
        page_list.append(first)

        if self.current_page == 1:
            prev = "<li><a href='#'>上一页</a></li>"
        else:
            prev = "<li><a href='index2?p=%s'>上一页</a></li>" % (self.current_page - 1,)
        page_list.append(prev)

        for i in self.page_number_range():
            if i == self.current_page:
                temp = "<li class='active'><a href='index2?p=%s'>%s</a></li>" % (i, i)
            else:
                temp = "<li><a href='index2?p=%s'>%s</a></li>" % (i, i)
            page_list.append(temp)

        if self.current_page == self.num_pages:
            next = "<li><a href='#'>下一页</a></li>"
        else:
            next = "<li><a href='index2?p=%s'>下一页</a></li>" % (self.current_page + 1,)
        page_list.append(next)

        last = "<li><a href='index2?p=%s'>尾页</a></li>" % (self.num_pages,)
        page_list.append(last)
        print(page_list)

        return ''.join(page_list)

#url对应的处理函数
def index2(request):
    from app01.page import Pagination
    current_page = request.GET.get('p')
    page_obj = Pagination(500,current_page)
    data_list = value_list[page_obj.start:page_obj.end]
    return render(request,'index2.html',{'data':data_list,'page_obj':page_obj})
<!--页面html文件-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.css">
</head>
<body>
    <ul>
        {% for d in data %}
            <li>{{ d.name }} {{ d.age }}</li>  <!--页面显示内容-->
        {% endfor %}
    </ul>
    
    <ul class="pagination pagination-sm">  <!--引用bootstrap的页码样式-->
        {{ page_obj.page_str|safe}}  <!--页码部分-->
    </ul>

</body>
</html>