首页 > 代码库 > django分页技术Paginator(进阶篇)

django分页技术Paginator(进阶篇)

一、概述

在之前的另一篇博文中介绍了在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):<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=http://www.mamicode.com/"?table=2&&page={{ user_review.previous_page_number }}" class="prev">{{ previous_link_decorator|safe }}上一页>
简单说明一下:

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


django分页技术Paginator(进阶篇)