Django框架(九、分页功能)

本文介绍了Django框架中的分页功能,包括Paginator对象、page对象及内置分页的使用。详细讲解了如何扩展Django内置分页,通过自定义CustomPaginator类并实现分页功能的补充。此外,还展示了如何使用BootStrap进行样式美化,提供了一个自定义插件式的分页解决方案,使得分页效果更加灵活且易于调用。

一、Django分页功能

1.Paginator对象

方法描述
per_page每页显示条目数量
count数据总个数
num_pages总页数
page_range总页数的索引范围,如: (1,10),(1,200)
pagepage对象

2.page对象

方法描述
has_next是否有下一页
next_page_number下一页页码
has_previous是否有上一页
previous_page_number上一页页码
object_list分页之后的数据列表
number当前页
paginatorpaginator对象

3.内置分页功能

views.py文件

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

User_list = []
for i in range(1,101):
    item = {"user"+str(i):i}
    User_list.append(item)


def index1(request):
    current_page = request.GET.get("p")
    paginator = Paginator(User_list, 10)
    try:
        # 这里将page对象定于为 ports
        ports = paginator.page(current_page)
    except PageNotAnInteger:
        ports = paginator.page(1)
    except EmptyPage:
        ports = paginator.page(paginator.num_pages)
    return render(request,"index1.html", {"ports":ports})
views.py

index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

    </style>
</head>
<body>


{% for user in ports.object_list %}
    <ul>{{ user }}</ul>
{% endfor %}

<div>
    {% if ports.has_previous %}
        <a href="/index1.html/?p={{ ports.previous_page_number }}">上一页</a>
        {% else %}
        <a href="#">首页</a>
    {% endif %}
    
    {% if ports.has_next %}
        <a href="/index1.html/?p={{ ports.next_page_number }}">下一页</a>
        {% else %}
        <a href="#">尾页</a>
    {% endif %}
</div>


</body>
</html>

在这里插入图片描述
Django内置的分页功能就只能做到这些事情,但这远远不能满足我们的需求,那么我们就需要对Django分页功能进行补充了。

二、Django分页功能的补充

  • 类Paginator是由Django内置的一个分页功能,但它能够完成的功能有限,那么我们就需要对其进行补充了。
  • 我们自定义CustomPaginator类,该类继承Paginator

扩展内置分页:views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger


class CustomPaginator(Paginator):
    def __init__(self, current_page, max_pager_num, *args, **kwargs):
        """
        :param current_page: 当前页
        :param max_pager_num:最多显示的页码个数
        :param args:
        :param kwargs:
        :return:
        """
        self.current_page = int(current_page)
        self.max_pager_num = max_pager_num
        super(CustomPaginator, self).__init__(*args, **kwargs)

    def page_num_range(self):
        # 当前页面
        # self.current_page
        # 总页数
        # self.num_pages
        # 最多显示的页码个数
        # self.max_pager_num
        print(1)
        if self.num_pages < self.max_pager_num:
            return range(1, self.num_pages + 1)
        print(2)
        part = int(self.max_pager_num / 2)
        if self.current_page - part < 1:
            return range(1, self.max_pager_num + 1)
        print(3)
        if self.current_page + part > self.num_pages:
            return range(self.num_pages + 1 - self.max_pager_num, self.num_pages + 1)
        print(4)
        return range(self.current_page - part, self.current_page + part + 1)


L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p')
    paginator = CustomPaginator(current_page, 11, L, 10)
    # per_page: 每页显示条目数量
    # count:    数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    # page:     page对象
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)

    return render(request, 'index.html', {'posts': posts})


扩展内置分页:Html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

    </style>
</head>
<body>
<div>
    <a href="/index1.html/?p=1">首页</a>
    {% if ports.has_previous %}
        <a href="/index1.html/?p={{ ports.previous_page_number }}">上一页</a>


    {% endif %}

    {% for foo in ports.paginator.page_num_range %}
        {% if foo ==  ports.number %}
            <a href="/index1.html/?p={{ foo }}" style="font-size: 30px;color: red">{{ foo }}</a>
            {% else %}
            <a href="/index1.html/?p={{ foo }}">{{ foo }}</a>
        {% endif %}


    {% endfor %}

    {% if ports.has_next %}
        <a href="/index1.html/?p={{ ports.next_page_number }}">下一页</a>

    {% endif %}
    <a href="/index1.html/?p={{ ports.paginator.num_pages }}">尾页</a>
    <span>{{ ports.number }}/{{ ports.paginator.num_pages }}</span>

</div>
</body>
</html>

扩展内置分页:Html

通过该分页功能大致实现的效果
在这里插入图片描述

三、自定制插件式分页功能

除了用系统提供的,我们可以自定义一个插件功能,这样的话,我们只需要将这个py文件保存在我们电脑的硬盘中,在我们需要时,调用就可以实现分页了,同时在定制时,还能为分页设置好样式。
在这里我们使用BootStrap来对我们的样式进行美化。

views.py文件

def index(request):
    from app.pager import Pagination
    current_page = request.GET.get("p")
    print(current_page)
    page_obj = Pagination(total_count=len(User_list),
                     current_page=current_page)
    print(page_obj.num_pages)
    data_list = User_list[page_obj.start():page_obj.end()]
    return render(request,"index.html",{"data_list":data_list,"page_obj":page_obj})

插件page.py文件


""""
配合插件 Bootstrap
"""

class Pagination(object):
    def __init__(self,total_count,current_page,per_page_num=20,max_page_num=7):
        """

        :param total_count: 所有数据的个数
        :param current_page:  当前页码
        :param per_page_num:  每页显示记录个数
        :param max_page_num:  分页现在最多页码个数
        """
        self.total_count=total_count
        try:
            self.current_page=int(current_page)
            if self.current_page < 1:
                self.current_page = 1
        except Exception as e:
            self.current_page = 1
        self.per_page_num=per_page_num
        self.max_page_num=max_page_num

    # 数据的索引首地址
    def start(self):
        return (self.current_page-1)*self.per_page_num

    # 数据的索引为地址
    def end(self):
        return (self.current_page)*self.per_page_num

    @property
    def num_pages(self):
        """

        :return: 总页数
        """
        a,b = divmod(self.total_count,self.per_page_num)
        if self.per_page_num == 0:
            return a
        return a+1

    def page_num_range(self):
        """
        自定义分页功能
        :return:  返回值是一个数组,该数组表示的是分页显示的页码
        """
        part = int(self.max_page_num/2) # 分页个数的中间值

        # 当页码总数小于显示分页数目时,所有页码显示
        if self.num_pages <= self.max_page_num:
            return range(1, self.num_pages+1)
        elif self.num_pages > self.max_page_num:
            # 当前页码小于分页的总数的中间值时,显示前几位分页页码
            if self.current_page<=part:
                return range(1,self.max_page_num+1)
            # 当前页码+中间值时大于总页码,显示后几位分页页码
            elif self.current_page+part>=self.num_pages:
                return range(self.num_pages - self.max_page_num + 1, self.num_pages + 1)
            # 显示需要显示的页码个数,并将当前页码居中
        return range(self.current_page-part,self.current_page+part+1)

    def page_str(self):
        """

        :return:  返回值是一个html格式的字符串,返回到前端直接调用就可以显示页码。运用的是插件Bootstrap
        """
        page_list = []

        # 首页按钮
        first_page = "<ul class='pagination'> <li ><a href='/index.html/?p=1'>首页</a></li>"
        page_list.append(first_page)

        # 如果存在上一页才有上一页按钮
        if self.current_page>1:
            prep_page = "<li><a href='/index.html/?p=%s'>上一页</a></li>"%(self.current_page-1)
            page_list.append(prep_page)

        # 中间序列的页码按钮
        for i in self.page_num_range():
            if i == self.current_page:
                temp = "<li class='active'><a href='/index.html/?p=%s' >%s</a></li>"%(i,i)
            else:
                temp = "<li><a href='/index.html/?p=%s' >%s</a></li>"%(i,i)
            page_list.append(temp)

        # 如果存在下一页才有下一页按钮
        if self.current_page< self.num_pages:
            next_page =  "<li><a href='/index.html/?p=%s'>下一页</a></li>"%(self.current_page+1)
            page_list.append(next_page)

        # 尾页按钮
        last_page = "<li><a href='/index.html/?p=%s'>尾页</a></li>  </ul>"%(self.num_pages)
        page_list.append(last_page)
        return " ".join(page_list)



index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugin/bootstrap/css/bootstrap.css">
    <style>
        * {
            padding: 0;
            margin: 0;
        }

    </style>
</head>
<body>


{% for row in data_list %}
    <ul>{{ row }}</ul>
{% endfor %}

<hr>
{% for current_page in page_obj.page_num_range %}
    <a href="/index.html/?p={{ current_page }}">{{ current_page }}</a>

{% endfor %}
<hr>
{{ page_obj.page_str | safe }}

</body>
</html>

通过该自定义插件,我们可以对比出,渲染后的区别
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值