Django自定义分页,实现paginator缺失的功能

有不少初学Django的朋友经常抱怨,在网上搜了一大堆教程,各种自定也分页的方法对新手一点都不友好,很难看懂。那今天我来写一个相对容易看懂的教程吧。

django内置paginator分页器虽然用起来是很简单,但是功能也很简单。一旦数据多起来,就会把页码分列成好几行,极不美观。那么要想自己限定当前最多显示前后多少页码,那要不就是重写paginator中的一些方法,或者用Listview。

但今天我更推荐初学者自己尝试自定义一个分页方法:

LIST = []
for i in range(209):
    LIST.append(i)
#这里就不用数据库的数据了,用个列表来举例,假设列表里有209条数据


def url_list(request): 
#url_list是我临时起的视图名称,大家按照自己urls.py里面对应url写就行
    current_page = request.GET.get('p',1)
    current_page = int(current_page)
    #获取当前页码
    total_count = len(LIST)
    #数据总长度
    per_page = 10
    #每页显示多少条数据
    max_page = 11
    #页面上始终保持最多显示多少页码
    start = (current_page-1) * per_page
    end = current_page * per_page
    #数据展示的起始点和结束点
    total_page,y = divmod(total_count,per_page)
    if y:
        total_page += 1
        #divmod()方法要是不知道就百度吧,用来整除和取余数用的。也就是假设每页10条数据,
        #那么209条数据可以分多少页,那么用209整除10就行了,要是有余数,就加一页,
        #余数也就是'y',总页数是'total_page'

    if current_page > total_page:
        current_page = total_page
    #如果当前页码比总页数还大,那就限定当前页等于总页数,不然你会有无穷的页码
    if max_page > total_page:
        max_page = total_page
    #如果最大页码也大于总页数,那就以说明数据量很少,分不足11页,那就让分页范围是总页数

    half_max_page = max_page -1// 2
    #half_max_page代表当前页码的前后各有多少页

    start_page = current_page - half_max_page
    end_page = current_page + half_max_page
    #起始页和结束页

    if start_page <= 1:
        start_page = 1
        end_page = max_page
    #如果起始页比1还小,那就定起始页显示为1,结束页为最大显示页数11,也就是【1、2、
    34567891011】,否则会出现负数页数显示在页面上
    if end_page > total_page:
        end_page = total_page
        start_page = total_page - max_page +1
    #如果结束页比总页数还大,那就定结束页为最后一页,起始页为总页数前10页,比如说总页数是20,那就是【10、11、12、13、14、15、16、17、18、19、20】,这是防止出现20页以后还出现更大的页码

    data = LIST[start:end]
    #这里就基本设置好了每页对应显示哪几条数据了,data是用来接收的变量,最后用来渲染的

    page_str = []
    #先创建一个空列表,用来接收等下要插入的html标签,最后渲染到模板里
    page_str.append('<div class="page"><a href="/url_list/?p=1">首页</a></div>')

    if current_page <= 1:
        page_str.append('<div class="page hide"><a href="/url_list/?p=%s">上一页</a></div>'%(current_page-1))
    else:
        page_str.append('<div class="page"><a href="/url_list/?p=%s">上一页</a></div>'%(current_page-1))
#如果当前页是第一页,那就不存在“上一页”的按钮了

    for i in range(start_page,end_page):
        if i == current_page:
            temp = '<div class="page active"><a href="/url_list/?p=%s">%s</a></div>' %(i,i)
        else:
            temp = '<div class="page"><a href="/url_list/?p=%s">%s</a></div>' %(i,i)

        page_str.append(temp)
#重点来了,这里的range(start_page,end_page)就是上面我们自己通过计算的出来的前后分页

    if current_page >= total_page:
         page_str.append('<div class="page hide"><a href="/url_list/?p=%s">下一页</a></div>'%(current_page+1))
    else:
        page_str.append('<div class="page"><a href="/url_list/?p=%s">下一页</a></div>'%(current_page+1))


    page_str.append('<div class="page"><a href="/url_list/?p=%s">尾页</a></div>'%(total_page))

    page_html = "".join(page_str)
#最后一定要拼接成字符串,再渲染,不然会出现很多类似'['的符号在网页上,你懂的
    return render(request,'url_list.html',{'data':data,'page_html':page_html})

还有在templates里的:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    .page{
        margin: 5px;
        background-color: pink;
        float: left }
    .active{
        background-color: blue }
    .hide{
        display: none }
    </style>
</head>
<body>
    <ul>
        {% for i in data %}
        <li>{{i}}</li>
        {% endfor %}
    </ul>
    {{page_html|safe}}

</body>
</html>

这样的大功告成了,你完全可以先把代码复制进去,自己试一下。至于网页的样式,完全是可以自己自定义的。

注意事项:

另外,其实像这种分页功能,理解了原理就行了,你不可能以后工作的时候动不动就几十行代码就为了个分页功能。这里给大家推荐一个我本人自己常用的“轮子”:EasyPage,只需要设置5各参数,分页想怎么设置就怎么设置,

原理和上面的代码一样,只是我自己封装成class了,用起来方便许多。

EasyPage地址:https://github.com/ChrisLee0211/django-EasyPage(具体用法都写在里面了,很简单的)

猜你喜欢

转载自blog.csdn.net/weixin_42833042/article/details/82393064