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_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直接传给前端,都可以实现同样的效果,看个人怎么决定,是放在后台还是前端。

时间: 2024-11-10 07:10:28

django分页技术Paginator(进阶篇)的相关文章

django分页技术paginator

分页是Web应用常用的手法,Django提供了一个分页器类Paginator(django.core.paginator.Paginator),可以很容易的实现分页的功能.该类有两个构造参数,一个是数据的集合,另一个是每页放多少条数据. 分页对象Paginator: 只需提供两个必要的参数,第一个就是用于展示的数据(object_list),第二参数就是每页显示的大小(per_page),提供了这两个参数,其他的都好说: Paginator.count:数据总量 Paginator.num_pa

django分页技术django-pagination和Paginator

转载前还请注明出处:http://blog.csdn.net/gugugujiawei 一.概述 几乎所有的web应用,都需要分页功能,但分页技术总体来说分两种,一种是全部加载,存于浏览器的缓存中,一种是分页访问,部分加载.前一种方法优点是实现简单,在一些对项目要求不多的特定应用上用得较多,可以利用的插件譬如datatables,而后一种方法优点是不会占用服务器太多的缓存,对于数据量大的列表项必须用到这种技术.由于我现在的项目属于管理后台,管理来自成千上万用户的数据,因而只能用到第二种方法.初期

基于WinSvr2016(TP)构建的&ldquo;超融合技术架构&rdquo;进阶篇

之前我有给大家介绍过<基于WinSrv2016(TP)构建的"超融合基础架构">,架构如下: 那大家还记得微软从Windows Server 2012推出的SOFS(横向扩展文件服务器)吗?忘了的话可以参考徐老师的博文<构建横向扩展文件服务器>,架构如下: 那么我今天想把2个东西合为一体,那么我接下来要做的就是超融合架构里再增加SOFS层上构建虚拟机,这样可以达到什么样的效果呢?最后我再告诉大家.那架构如下: 那基于之前的环境,我来构建SOFS吧: 选择SOFS

Python之路【第十七篇】:Django【进阶篇 】

Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost')

Python之路【第十七篇】:Django之【进阶篇】

Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost')

Python之路【第十七篇】:Django【进阶篇】

Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost')

Django【进阶篇 】(地阶段位二)

Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cur

Python之路,Day15 - Django适当进阶篇

Python之路,Day15 - Django适当进阶篇 本节内容 学员管理系统练习 Django ORM操作进阶 用户认证 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣和效率最高的,今天就来基于下面的需求来继续学习Django 项目需求: 1.分讲师\学员\课程顾问角色,2.学员可以属于多个班级,学员成绩按课程分别统计3.每个班级至少包含一个或多个讲师4.一个学员要有状态转化的过程 ,比如未报名前,报名后,毕业老学员5.客户要有咨询纪录, 后续的定期跟踪纪录也要保存6

django orm 分页(paginator)取数据出现警告manage.py:1: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: &lt;class &#39;sign.models.Guest&#39;&gt; QuerySet.

使用django的orm做分页(Paginator)时出现了下面的警告 In [19]: p=Paginator(guest_list,2) manage.py:1: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <class 'sign.models.Guest'> QuerySet. #!/usr/bin/env python 网上搜的