# 分页及优化 如果需要返回内容过多,就需要进行分页处理,比如搜索某一个关键字,需要返回几千几万条内容,如果 只是一个网页内显示,效果太差,此时一般使用分页。 ![分页](./imgs/fenye.png) > Django提供了一些类实现管理数据分页,这些类位于django/core/paginator.py中 > ## Paginator 对象 - Paginator(列表,int):返回分页对象,参数为列表数据,每面数据的条数 - 属性 - count:对象总数 - num_pages:页面总数 - page_range:页码列表,从1开始,例如[1, 2, 3, 4] - 方法 - page(num):下标以1开始,如果提供的页码不存在,抛出InvalidPage异常 - 异常exception - InvalidPage:当向page()传入一个无效的页码时抛出 - PageNotAnInteger:当向page()传入一个不是整数的值时抛出 - EmptyPage:当向page()提供一个有效值,但是那个页面上没有任何对象时抛出 ## Page对象 - 创建对象 - Paginator对象的page()方法返回Page对象,不需要手动构造 - 属性 - object_list:当前页上所有对象的列表 - number:当前页的序号,从1开始 - paginator:当前page对象相关的Paginator对象 - 方法 - has_next():如果有下一页返回True - has_previous():如果有上一页返回True - has_other_pages():如果有上一页或下一页返回True - next_page_number():返回下一页的页码,如果下一页不存在,抛出InvalidPage异常 - previous_page_number():返回上一页的页码,如果上一页不存在,抛出InvalidPage异常 - len():返回当前页面对象的个数 - 迭代页面对象可以访问当前页面中的每个对象 ## 问题提出: >现在假设已知有100页数据,当前是第1页,要得出1-10的页码数, >而当前如果是第50页,则要输出46-55的页码数 ``` def pageshow(count,p): ''' count 总页数,p 当前页 begin 开始页 end 结束页 ''' # 开始页 begin = p-4 # 结束页 end = p+5 # 判断如果当前页 小于5 if p < 5: # 则开始页为1 begin = 1 # 结束页为10 end = 10 # 判断如果当前页 大于 总页数-5 if count<10: begin=1 end = count # 当前页如果大于总页数-5 if p > count-5: # 则开始页为总页数-9 begin = count - 9 # 结束页为总页数 end = count # 判断如果开始页 小于等于 0,则开始页为1 if begin <= 0: begin = 1 for x in range(begin,end+1): print(x) pageshow(100,96) ``` ## 自定义过滤器 在当前应用目录下创建templatetags目录和pagetag.py文件, 可以在模板中使用`{ % load pagetag % }`加载 > 注意:templatetags目录名不能更改,pagetag.py文件可以自定义,但对应的在模板中加载时也需要更改名字 ``` from django import template register = template.Library() from django.utils.html import format_html # 自定义过滤器 @register.filter def py11_upper(val): # print ('val from template:',val) return val.upper() # 自定义乘法运算标签 @register.simple_tag def cheng(var1,var2): res = float(var1) * float(var2) return '%.2f'%res # 自定义分页标签 @register.simple_tag def showpage(count,request): # 获取当前页 p = int(request.GET.get('p',1)) # 获取当前页面中的请求参数 get args = request.GET.dict() u = '' for k,v in args.items(): if k != 'p': u += '&'+k+'='+v # 开始页 begin = p-4 # 结束页 end = p+5 # 判断如果当前页 小于5 if p < 5: # 则开始页为1 begin = 1 # 结束页为10 end = 10 # 判断如果当前页 大于 总页数-5 if count<10: begin=1 end = count # 当前页如果大于总页数-5 if p > count-5: # 则开始页为总页数-9 begin = count - 9 # 结束页为总页数 end = count # 判断如果开始页 小于等于 0,则开始页为1 if begin <= 0: begin = 1 s = '
  • 总页数:'+str(count)+'
  • ' s+= '
  • 首页
  • ' for x in range(begin,end+1): if p == x: s+= '
  • '+str(x)+'
  • ' else: s+= '
  • '+str(x)+'
  • ' s+= '
  • 尾页
  • ' return format_html(s) ``` ## 定义路由 ``` # 后台商品列表 url(r'^goodsindex', goodsviews.goodsindex,name="goodsindex"), ``` ## 定义视图函数,并查询数据,进行分页 ``` # 获取查询条件 v = request.GET.get('keywords','') # Q对象 from django.db.models import Q ob = Goods.objects.filter(Q(id__contains=v)|Q(title__contains=v)|Q(typeid__name__contains=v)|Q(price__contains=v)|Q(status__contains=status)) # 数据分页 from django.core.paginator import Paginator # 实例化分页类 paginator = Paginator(ob,2) # 获取当前页码 p = int(request.GET.get('p',1)) # 获取分页数据对象[{id:1},{id:2}] [{id:3},{id:4}] goodslist= paginator.page(p) # 分配数据 context = {'goods':goodslist} ``` ## 定义模板,加载数据和分页数据 ``` { % load adminpagetag % } { % PageShow goods.paginator.num_pages request % } ```