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 % }
```