django分页技术Paginator(进阶篇)

来源:互联网 发布:西安交大管晓宏 知乎 编辑:程序博客网 时间:2024/04/30 12:03

一、概述

在之前的另一篇博文中介绍了在django中进行分页的两种方法,可是说基本上实现了分页刷新的功能,但存留一个问题,那就是当页数多的时候,会出现所有页码排开的情况,美观性不好不说,更主要的是当页码多的时候,分页栏会变得很长。所以对之前的做法进行重构的同时,也实现了定义分页栏显示页码个数的功能。

最终效果:


本博文旨在深化理解Paginator的使用,当然熟悉后也可以实现“跳转”,“下5页”类似的功能。


二、Paginator

博文提到,在一个页面中使用多个表,利用url形式诸如 http://XXX.html?table=4&&page=2,其中table为第几个表,page表示该表对应的当前页码。

于是在,views.py解析url,利用的是request的get方法

from hello.paging import get_page_msgdef user_review(req):......    page=req.GET.get('page','')    if page == '':        page = 1    table=req.GET.get('table','')    if table == '':        table = 1    selectItemList=[user,user_review]    index=int(table)-1    count=len(selectItemList)    resultItem,p_pages=get_page_msg(limit,selectItemList,index,count,page)    return render_to_response('user-review.html',{'user':resultItem[0],'p_pages_user':p_pages[0],'user_review':resultItem[1],'p_pages_user_review':p_pages[1]},context_instance=RequestContext(req))


解释一下:

page,table------------------初始化都为1

limit---------------------------每个表中每页显示的项目数,利用ajax技术可以实现像datatables更改项目数的效果

selectItemList------------- 一个列表,每一项都是一个表中的原始数据

index-------------------------当前点击是第几个表,第0个开始

count------------------------表的个数,即selectItemList的长度

page-------------------------当前选中表即将显示的页码,非选中表将回到首页

resultItem----------------- 一个列表,每一个项都是一个Paginator.page()实例

p_pages-------------------一个列表,每一项代表了即将显示的页码列表


于是重点就是get_page_msg()这个函数了。封装如下:

#coding:utf-8from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger'''参数1:每页显示的条数参数2:待显示数据列表参数3:翻页时对应的表单参数4:共处理表的数目参数5:翻页时对应表对应的页码前两个参数设置所有表后三个参数只对应鼠标点击相应的表'''def get_page_msg(limit,selectItemList,index,count,page):p_pages = []resultItem = []for i in range(count):selectItemList[i]=Paginator(selectItemList[i],limit)p_pages.append(selectItemList[i].page_range[0:7])resultItem.append(selectItemList[i].page(1))if int(page) < 4:   #这里进行判断,假如当前页小于5的时候,        p_pages[index] = selectItemList[index].page_range[0:7]    #pr为获取页码列表,即当前页小于4的时候,模板中将显示第1页至第7页,如 1 2 3 4 5 6 7elif int(selectItemList[index].num_pages)-int(page) < 4:   #假如最后页减当前页小于4时num_pages=int(selectItemList[index].num_pages)        p_pages[index] = selectItemList[index].page_range[num_pages-7:num_pages]  #页码列表显示最后7页,如共有30页的话,那显示:24 25 26 27 28 29 30else:   #其它情况        p_pages[index] = selectItemList[index].page_range[int(page)-4:int(page)+3]   #其它情况显示当前页的前3条至后3条,如当前在第10页的话,那显示: 7 8 9 10 11 12 13 try:resultItem[index] = selectItemList[index].page(page)except EmptyPage:resultItem[index] = selectItemList[index].page(selectItemList[index].num_pages)return resultItem,p_pages

解释一下:

for...range...-----------------------做了三件事,新建count个Paginator实例组成的列表、count个默认显示范围7页组成的列表、count个默认Paginator.page(1)实例组成的列表

.page_range---------------------页码总范围列表,利用切片操作时,超过范围自动切到最后一个(python切片操作功能)

.num_pages-------------------- 页码最后一个的数字

这些操作可以封装为一个类,参考http://www.linuxyw.com/309.html


然后更改了,前段代码:

user-review.html

<div>       {%  include "pages/user_review.html" %}</div>

pages/user-review.html

<ul style="float:left">    共 <span>{{ user_review.paginator.count }}</span> 条任务,总 <span>{{ user_review.paginator.num_pages }}</span> 页</ul><ul class="pagination" style="float:right">{% if user_review.has_previous %}    <li><a href="?table=2&&page={{ user_review.previous_page_number }}" class="prev">{{ previous_link_decorator|safe }}上一页</a></li>{% else %}    <li class="paginate_button previous disabled"><span class="disabled prev">{{ previous_link_decorator|safe }}上一页</span></li>{% endif %}{% if user_review.has_previous %}    <li><a href="?table=2&&page=1" class="prev">{{ previous_link_decorator|safe }}首页</a></li>{% else %}    <li class="paginate_button previous disabled"><span class="disabled prev">{{ previous_link_decorator|safe }}首页</span></li>{% endif %}{% for page in p_pages_user_review %}{% if page %}{% ifequal page user_review.number %}<li class="active"><span class="current page">{{ page }}</span></li>{% else %}<li><a href="?table=2&&page{{ page_suffix }}={{ page }}{{ getvars }}" class="page">{{ page }}</a></li>{% endifequal %}{% endif %}{% endfor %}  {% if user_review.has_next %}  <li><a href="?table=2&&page={{ user_review.paginator.num_pages }}" class="next">末页{{ next_link_decorator|safe }}</a></li> {% else %}        <li class="paginate_button next disabled"><span class="disabled next">末页{{ next_link_decorator|safe }}</span></li>{% endif %}  {% if user_review.has_next %}        <li><a href="?table=2&&page={{ user_review.next_page_number }}" class="next">下一页{{ next_link_decorator|safe }}</a></li>{% else %}        <li class="paginate_button next disabled"><span class="disabled next">下一页{{ next_link_decorator|safe }}</span></li>{% endif %}</ul>

简单说明一下:

当从views.py传来一个Paginator.page()对象时,可以调用xxx.paginator.num_pages得到最后一页的页码,等同于你在views.py中利用Paginator.num_pages直接传给前端,都可以实现同样的效果,看个人怎么决定,是放在后台还是前端。


0 0