分页是指,把从数据库中查询到的结果,分块展示在前台,通常不会把所有查询到的结果一次性展示,这样会造成数据库压力,造成资源浪费.
-
分页早些时候了解过,但是自己实践,还是需要花一定的时间
-
分页有orm的Paginator,这里举个使用原生SQL的例子
-
这里给的是Python+MySQL的原生查询的例子,用到的是django的框架,配合自定义标签,渲染前台
1.本例使用了django的自定义标签,在app/templatetags/tags.py ,自定义标签,让前台也能调用后台的函数,扩展其中的功能
#-*-coding:utf-8-*-
from django import template
import urlparse
import urllib
from django.utils.safestring import mark_safe
register=template.Library()
.simple_tag
def div_page(curr_page,total,count,curr_url,request_url):
'''分页栏5列'''
max_page_count=5
'''查询的数据的总记录/每页显示的数量,的出来的就是有多少页啦'''
list_len=int(total)/count + 1
'''如果第一页就装完了,长度就是1了'''
if list_len==0:list_len=1
'''所有页面做出一个列表'''
page_range=range(1,list_len + 1)
'''中间位置的索引,注意是索引,不是位置'''
center_index = max_page_count / 2
'''当前页面的索引,其实就是当前的页面再列表中的位置取索引,索引使用index(元素)获取'''
curr_index=page_range.index(curr_page)
'''这个函数是获取url地址中的?后面的参数a=11&b=12,转化为字典,因为字典容易替换内容'''
def parse_qs(qs):
res = {}
if not qs:
return res
params = qs.split("&")
for p_str in params:
k, v = p_str.split("=")
res[k] = urllib.unquote(v)
return res
'''需要编码中文成为utf8,否则中文在地址栏中会出现乱码'''
params = parse_qs(urlparse.urlparse(request_url).query.encode("utf8"))
'''分页的html便签串'''
page_str = '<div class="pagenation">'
'''定义首页'''
params['p']=1
page_str += '<a href="%s?%s" style="background-color: pink"> 首页 </a>' % (curr_url,'&'.join(['%s=%s'%(k,v) for k,v in params.items()]))
'''定义上一页'''
if curr_page !=1:
params['p']=curr_page-1
page_str += '<a href="%s?%s" style="background-color: #5bc0de">上一页</a>' % (curr_url,'&'.join(['%s=%s'%(k,v) for k,v in params.items()]))
'''定义1,2,3,4,5这种中间列的按钮,当前索引大于中间位置的索引时,截断前面的部分,用当前位置的索引减去中间位置的索引进行切片:'''
if curr_index>=center_index:
page_range=page_range[curr_index-center_index:]
'''遍历每一个便签,并转成html'''
for i in enumerate(page_range):
params['p']=i[1]
'''当前页需要加粗加深'''
if i[1] == curr_page:
page_str += '<a href="%s?%s" class="active" style="background-color: #1b6d85">%s</a>' % (curr_url, '&'.join(['%s=%s'%(k,v) for k,v in params.items()]), i[1])
elif i[0]+1<=max_page_count:
page_str += '<a href="%s?%s" >%s</a>' % (curr_url,'&'.join(['%s=%s'%(k,v) for k,v in params.items()]), i[1])
else:
'''超过最大分页栏的5个数字时,退出'''
break
'''定义下一页'''
if curr_page !=page_range[-1]:
params['p']=curr_page+1
page_str += '<a href="%s?%s" style="background-color: #5bc0de"> 下一页 </a>' % (curr_url,'&'.join(['%s=%s'%(k,v) for k,v in params.items()]))
'''定义末页'''
params['p']=list_len
page_str += '<a href="%s?%s" style="background-color: pink"> 末页 </a>' % (curr_url,'&'.join(['%s=%s'%(k,v) for k,v in params.items()]))
page_str += "</div>"
'''使用make_safe渲染为html标签而不是字符串'''
return mark_safe(page_str)
2.前台因为要使用自定义标签,所以必须{% load tags %}
引入templatetags/tags.py
{% load tags %}
...
<br>
{% div_page p total count url request.get_full_path %}
<br>
3.视图部分的逻辑,首先对查询语句的查询总数据进行汇总,再根据需要显示的记录数,配合mysql的limit函数进行切片,取数之前,先进行分页,完之后才显示,这样对数据库的开销没有那么大,也是值得推荐的.
def get_lc(request):
oDate=request.GET.get('oDate','')
oDepCity=request.GET.get('oDepCity','')
oArrCity=request.GET.get('oArrCity','')
p=int(request.GET.get('p',1))
count=int(request.GET.get('count',20))
print count
title,data,total=get_data(oDate,oDepCity,oArrCity,p,count)
return render(request,'lc.html',locals())
def get_data(oDate,oDepCity,oArrCity,p,count):
if oDate:
if oDepCity and oArrCity:
v_sql="SELECT t.oDate 日期,t.oDepCity 出发,t.oArrCity 到达,t.flightNo 航班,t.depTime 出发时间,t.arrTime 到达时间,t.code 机型,t.airportTax 机场税,t.timeDuringFlight 历时,t.nameZH 舱位,t.info 余票,t.adultMileage 里程,t.awardDiscount 促销,t.discountPrice 折扣,t.create_date as 更新时间 from csair_lc t inner join (select a.oDate,a.flightNo,a.adultMileage,a.oArrCity,a.oDepCity,max(a.create_date) create_date from csair_lc a where a.create_date>=NOW()-10000 and a.oDate='{0}' and a.oArrCity='{1}' and a.oDepCity='{2}' group by a.oDate,a.flightNo,a.adultMileage,a.oArrCity,a.oDepCity) b on b.create_date=t.create_date and b.oDate=t.oDate and t.flightNo=b.flightNo and t.adultMileage=b.adultMileage and t.oDepCity=b.oDepCity and t.oArrCity=b.oArrCity order by t.oDate,t.depTime".format(oDate,oArrCity,oDepCity)
'''部分sql语句省略'''
conn=mysqlpool.connection()
cur=conn.cursor()
cur.execute('select count(1) from (%s) _count'%v_sql)
total=cur.fetchone()[0]
# print total,count
if not total:
return None,None,total
v_sql+=' limit {0},{1}'.format((int(p)-1)*int(count),count)
cur.execute(v_sql)
title=cur.description
data=cur.fetchall()
conn.close()
return title,data,total
附带一个效果图!可以妥妥的显示当前页,下一页,末页,首页…色彩搭配不喜勿喷.
最新评论