分页的实现

分页是指,把从数据库中查询到的结果,分块展示在前台,通常不会把所有查询到的结果一次性展示,这样会造成数据库压力,造成资源浪费.

  • 分页早些时候了解过,但是自己实践,还是需要花一定的时间
  • 分页有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()
​
@register.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

附带一个效果图!可以妥妥的显示当前页,下一页,末页,首页…色彩搭配不喜勿喷.

 

Paginator的话,网上一大堆例子,就不举例了,如果有需要在进行交流.写前端还是挺费时间的.找机会把ajax的分页给整出来.今天就这样,祝大家五一节快乐.


谢谢观赏,有疑问请留言

赞(0)
未经允许不得转载:http://www.yueguangzu.net逗逗网 » 分页的实现
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址