一、概述
在之前的另一篇博文中介绍了在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_msg def user_review(req): <span style="white-space:pre"> </span>... <span style="white-space:pre"> </span>... <span style="white-space:pre"> </span>page=req.GET.get('page','') <span style="white-space:pre"> </span>if page == '': <span style="white-space:pre"> </span>page = 1 <span style="white-space:pre"> </span>table=req.GET.get('table','') <span style="white-space:pre"> </span>if table == '': <span style="white-space:pre"> </span>table = 1 <span style="white-space:pre"> </span>selectItemList=[user,user_review] <span style="white-space:pre"> </span>index=int(table)-1 <span style="white-space:pre"> </span>count=len(selectItemList) <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>resultItem,p_pages=get_page_msg(limit,selectItemList,index,count,page) <span style="white-space:pre"> </span>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-8 from 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 7 elif 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 30 else: #其它情况 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> <span style="white-space:pre"> </span>{% 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直接传给前端,都可以实现同样的效果,看个人怎么决定,是放在后台还是前端。