html分页器的实现原理,Django之分页器

Django自带分页器的实现

介绍

Django提供了一个新的类来帮助你管理分页数据,这个模块存放在django.core.paginator.py。

其中有两个核心类,一个是Paginator类,另一个是Page类。

Paginator类

初始化操作

class Paginator(object):

def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):

self.object_list = object_list

self.per_page = int(per_page)

self.orphans = int(orphans)

self.allow_empty_first_page = allow_empty_first_page

self._num_pages = self._count = None

解释:

object_list:可以是列表,元组,查询集或其他含有 count() 或 len()方法的可切片对象。对于连续的分页,查询集应该有序,例如有order_by()项或默认ordering参数。

per_page:每一页中包含条目数目的最大值,不包括独立成页的那页。(见下面 orphans参数解释)。

orphans=0:当你使用此参数时说明你不希望最后一页只有很少的条目。如果最后一页的条目数少于等于orphans的值,则这些条目会被归并到上一页中(此时的上一页变为最后一页)。

allow_empty_first_page=True: 默认允许第一页为空。

类方法:

Paginator.page(number):根据参数number返回一个Page对象。(number为1的倍数)

类属型:

Paginator.count:所有页面对象总数,即统计object_list中item数目。

当计算object_list所含对象的数量时, Paginator会首先尝试调用object_list.count()。

如果object_list没有 count() 方法,Paginator 接着会回退使用len(object_list)。

Pagnator.num_pages:页面总数。

pagiator.page_range:页面范围,从1开始,例如[1,2,3,4]。

Page类

初始化操作

class Page(collections.Sequence):

def __init__(self, object_list, number, paginator):

self.object_list = object_list

self.number = number

self.paginator = paginator

类方法

Page.has_next() 如果有下一页,则返回True。

Page.has_previous() 如果有上一页,返回 True。

Page.has_other_pages() 如果有上一页或下一页,返回True。

Page.next_page_number() 返回下一页的页码。如果下一页不存在,抛出InvlidPage异常。

Page.previous_page_number() 返回上一页的页码。如果上一页不存在,抛出InvalidPage异常。

Page.start_index() 返回当前页上的第一个对象,相对于分页列表的所有对象的序号,从1开始。

比如,将五个对象的列表分为每页两个对象,第二页的start_index()会返回3。

Page.end_index() 返回当前页上的最后一个对象,相对于分页列表的所有对象的序号,从1开始。

比如,将五个对象的列表分为每页两个对象,第二页的end_index() 会返回 4。

类属型

Page.object_list 当前页上所有对象的列表。

Page.number 当前页的序号,从1开始。

Page.paginator 相关的Paginator对象。

异常处理

InvalidPage(Exception): 异常的基类,当paginator传入一个无效的页码时抛出。

Paginator.page()放回在所请求的页面无效(比如不是一个整数)时,或者不包含任何对象时抛出异常。通常,捕获InvalidPage异常就够了,但是如果你想更加精细一些,可以捕获以下两个异常之一:

exception PageNotAnInteger,当向page()提供一个不是整数的值时抛出。

exception EmptyPage,当向page()提供一个有效值,但是那个页面上没有任何对象时抛出。

这两个异常都是InalidPage的子类,所以可以通过简单的except InvalidPage来处理它们。

使用方式

views.py

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

from django.shortcuts import render

def listing(request):

contact_list = Contacts.objects.all() # 获取所有contacts,假设在models.py中已定义了Contacts模型

paginator = Paginator(contact_list, 25) # 每页25条

page = request.GET.get('page')

try:

contacts = paginator.page(page) # contacts为Page对象!

except PageNotAnInteger:

# If page is not an integer, deliver first page.

contacts = paginator.page(1)

except EmptyPage:

# If page is out of range (e.g. 9999), deliver last page of results.

contacts = paginator.page(paginator.num_pages)

return render(request, 'list.html', {'contacts': contacts})

*.html

{% for contact in contacts %}

{# Each "contact" is a Contact model object. #}

{{ contact.full_name|upper }}

...

{% endfor %}

或者另一种形式

存在问题

描述

上面这种分页方式,在数据量较小的时候是没有效率问题,但是随着数据量的不断增大,查询速度越来越慢。

Django分页器优化的实现

原理

利用Django查询集的惰性查询特性

实现

def owner_page(request, obj):

"""

# 自定义分页器

:param request: request请求

:param obj: 分页对象

:return: 所在页码的对象集,所有页码,当前页码,分页对象的总数

"""

current_page = 1

all_page = 1

page_type = ''

try:

current_page = int(request.GET.get('cur', '1'))

all_page = int(request.GET.get('all', '1'))

page_type = str(request.GET.get('action', '')) # 向前翻页还是向下翻页

except ValueError:

current_page = 1

all_page = 1

page_type = ''

if page_type == 'next':

current_page += 1

elif page_type == 'previous':

current_page -= 1

if isinstance(obj, list):

count = len(obj)

else:

count = obj.count()

start = (current_page - 1) * PAGE_SIZE

end = current_page * PAGE_SIZE

data = obj[start:end]

if current_page == 1 and current_page == 1: # 标记1

all_page = math.ceil(count / PAGE_SIZE)

return data, all_page, current_page, count

使用方式

views.py

def get_all_goods(request):

user_id = request.session.get('user_id')

goods = Good.objects.get_user_goods(user_id=user_id)

data, all_page, current_page, count = owner_page(request, goods)

return render(

request,

"goods_all_list.html",

{'data': data, 'allPage': all_page, 'curPage': current_page, 'count': count}

)

page.html

  • style="color:blank;sex:black;border:1px solid #ddd;">共{{ count }}条记录

goods_all_list.html

...

{% include "page.html" %}

...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值