8. 分页及优化¶
如果需要返回内容过多,就需要进行分页处理,比如搜索某一个关键字,需要返回几千几万条内容,如果 只是一个网页内显示,效果太差,此时一般使用分页。
Django提供了一些类实现管理数据分页,这些类位于django/core/paginator.py中
8.1. Paginator 对象¶
- Paginator(列表,int):返回分页对象,参数为列表数据,每面数据的条数
- 属性
- count:对象总数
- num_pages:页面总数
- page_range:页码列表,从1开始,例如[1, 2, 3, 4]
- 方法
- page(num):下标以1开始,如果提供的页码不存在,抛出InvalidPage异常
- 异常exception
- InvalidPage:当向page()传入一个无效的页码时抛出
- PageNotAnInteger:当向page()传入一个不是整数的值时抛出
- EmptyPage:当向page()提供一个有效值,但是那个页面上没有任何对象时抛出
8.2. 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():返回当前页面对象的个数
- 迭代页面对象可以访问当前页面中的每个对象
8.3. ¶
问题提出:
现在假设已知有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)
8.4. 自定义过滤器¶
在当前应用目录下创建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 = '<li>总页数:'+str(count)+'</li>'
s+= '<li><a href="?p=1'+u+'">首页</a></li>'
for x in range(begin,end+1):
if p == x:
s+= '<li class="am-active"><a href="?p='+str(x)+u+'">'+str(x)+'</a></li>'
else:
s+= '<li><a href="?p='+str(x)+u+'">'+str(x)+'</a></li>'
s+= '<li><a href="?p='+str(count)+u+'">尾页</a></li>'
return format_html(s)
8.5. 定义路由¶
# 后台商品列表
url(r'^goodsindex', goodsviews.goodsindex,name="goodsindex"),
8.6. 定义视图函数,并查询数据,进行分页¶
# 获取查询条件
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}
8.7. 定义模板,加载数据和分页数据¶
```
{ % load adminpagetag % }
{ % PageShow goods.paginator.num_pages request % }
```