Django框架 分页

一.内置分页
1.分页原理:

#views.py:

from django.shortcuts import render

USER_LIST=[]
for i in range(1,999):
    temp={"name":"root"+str(i),"age":i}
    USER_LIST.append(temp)

def index(req):
    per_page_count=10
    current_page=int(req.GET.get("p"))
    #相应的URL应为/index.html?p=2的形式
    start=(current_page-1)*per_page_count
    end=current_page*per_page_count
    data=USER_LIST[start:end]
    prev_page=current_page-1#不过还需要判断是否有上/下1页
    next_page=current_page+1
    return render(req,"index.html",{"user_list":USER_LIST,"prev_page":prev_page,"next_page":next_page})
<!--index.html-->

<body>
	<ul>
	    {% for row in user_list %}
	        <li>{{row.name}}-{{row.age}}</li>
        {% endfor %}
        <a href="/index.html?p={{prev_page}}">上一页</a>
        <a href="/index.html?p={{next_page}}">下一页</a>
	</ul>
</body>

2.语法

  • Django的内置分页只能完成"上一页"/"下一页"的操作,如果需要跳转到指定页等其他功能,需扩展/自定制

(1)Paginator对象:

<pagi>=Paginator(<DL>,<n>):创建Paginator对象
  #参数说明:
    DL:所有数据构成的列表
      #因为Django中的延迟加载机制,这么做不会导致服务器崩溃
      #即.all()获取所有数据时并不真正得到数据,将数据显示在屏幕上时才真正得到需要的数据
    n:每页显示的数据条数
    pagi:返回Paginator对象

#Paginator对象中封装的属性:
<pagi>.per_page:每页显示条目数量
<pagi>.count:数据总个数
<pagi>.num_pages:总页数
<pagi>.page_range:总页数的索引范围(页码范围)
<pagi>.page:Page对象

(2)Page对象:

<pag>=<pagi>.page(<num>):创建Page对象
  #参数说明:
    pagi:Paginator对象
    num:当前页的页码(创建的Page对象的页码)
    pag:返回Page对象

#Page对象中封装的属性:
<pag>.has_next:是否有下1<pag>.next_page_number:1页的页码
<pag>.has_previous:是否有上1<pag>.previous_page_number:1页的页码
<pag>.object_list:本页的数据列表
<pag>.number:当前页的页码
<pag>.paginator:Paginator对象

(3)相关错误:

PageNotAnInteger:输入的页码不合法(不为整数)
EmptyPage:输入的页码合法但该页不存在

3.实例:

#views.py:

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

#创建数据:
L=[]
for i in range(999):
    L.append(i)

#视图函数:
def index(request):
    current_page=request.GET.get("p")
    paginator=Paginator(L,10)
    #创建Paginator对象,L是全部数据构成的列表,10为每页显示的数据条数
    try:
        posts=paginator.page(current_page)
        #生成Page对象,current_page是页码
    except PageNotAnInteger:#表示指定的页码不合法(不是整数)
        posts=paginator.page(1)
    except EmptyPage:#表示没有指定的页码
        posts=paginator.page(paginator.num_pages)
    return render(request,'index.html',{'posts':posts})
<!--index.html:-->

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <ul>
    {% for item in posts %}
	  <li>{{ item }}</li>
	{% endfor %}
  </ul>
  {% include "include/pager.html" %}<!--进行模板继承-->
</body>
</html>
<!--include/pager.html-->

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <div class="pagination">
    <span class="step-links">
	  {% if posts.has_previous %}
	    <a href="/index.html?p={{posts.previous_page_number}}">Previous</a>
	  {% else %}
		<a href="#">Previous</a>
	  {% endif %}
	  <span class="current">
	    {{posts.number}}/{{posts.paginator.num_pages}}
	  </span>
	  {% if posts.has_next %}
	    <a href="/index.html?p={{posts.next_page_number}}">Next</a>
	  {% else %}
        <a href="#">Next</a>
	  {% endif %}
    </span>
  </div>
</body>
</html>

4.扩展内置分页:

原理是自定义1个类,该类继承Paginator类并进行了扩展
#views.py:

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

class CustomPaginator(Paginator):
    def __init__(self,current_page,max_pager_num,*args,**kwargs):
        #current_page:当前页的页码
        #max_pager_num:最多显示的页码个数
        self.current_page=int(current_page)
        self.max_pager_num=max_pager_num
        super(CustomPaginator,self).__init__(*args,**kwargs)
    def page_num_range(self):
        #num_pages:(继承来的)总页数
        #current_page:当前页的页码
        #max_pager_num:最多显示的页码个数
        if self.num_pages<self.max_pager_num:
            return range(1,self.num_pages+1)
        part=int(self.max_pager_num/2)
        if self.current_page<=part:
            return range(1,self.max_pager_num+1)
        if self.current_page+part>self.num_pages:
            return range(self.num_pages+1-self.max_pager_num,self.num_pages+1)
        return range(self.current_page-part,self.current_page+part+1)

L=[]
for i in range(999):
    L.append(i)

def index(request):
    current_page=request.GET.get('p')
    paginator=CustomPaginator(current_page,11,L,10)
    #current_page是当前页的页码,11是最多显示的页数,L是全部数据构成的列表,10是没有显示数据的条数
    try:
        posts=paginator.page(current_page)
    except PageNotAnInteger:
        posts=paginator.page(1)
    except EmptyPage:
        posts=paginator.page(paginator.num_pages)
    return render(request,'index.html',{'posts':posts})
<!--index.html:-->

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <ul>
    {% for item in posts %}
      <li>{{ item }}</li>
    {% endfor %}
  </ul>
  <div class="pagination">
    <span class="step-links">
      {% if posts.has_previous %}
        <a href="/index.html?p={{posts.previous_page_number}}">Previous</a>
      {% endif %}
      {% for i in posts.paginator.page_num_range %}
        <a href="/index.html?p={{i}}">{{i}}</a>
      {% endfor %}
      {% if posts.has_next %}
        <a href="/index.html?p={{posts.next_page_number}}">Next</a>
      {% endif %}
    </span>
    <span class="current">
      {{posts.number}}/{{posts.paginator.num_pages}}
    </span>
  </div>
</body>
</html>

二.自定义分页

要求传入:
1.数据总条数
2.当前页的页码
3.每页最多显示的数据条数
4.每页最多显示的页码数
#app01/migrations/pager.py:

class Paginator(object):
    def __init__(self,totalCount,currentPage,perPageItemNum=30,maxPageNum=7):
        self.total_count=totalCount#数据总条数
        try:
            v=int(currentPage)#当前页的页码
            if v <=0:
                v=1
            self.current_page=v
        except Exception as e:
            self.current_page=1
        self.per_page_item_num=perPageItemNum#每页最多显示的数据条数
        self.max_page_num=maxPageNum#每页最多显示的页码数
    def start(self):#本页第1条数据的索引
        return (self.current_page-1)*self.per_page_item_num
    def end(self):#本页最后1条数据的索引
        return self.current_page*self.per_page_item_num
    @property
    def num_pages(self):#页码范围
        a,b=divmod(self.total_count,self.per_page_item_num)
        if b==0:
            return a
        return a+1
    def page_num_range(self):#显示的页码的范围
        if self.num_pages<self.max_page_num:
            return range(1,self.num_pages+1)
        part=int(self.max_page_num/2)
        if self.current_page<=part:
            return range(1,self.max_page_num+1)
        if self.current_page+part>self.num_pages:
            return range(self.num_pages+1-self.max_page_num,self.num_pages+1)
        return range(self.current_page-part,self.current_page+part+1)
    def page_str(self):#返回某页显示的全部页码构成的标签
        page_list=[]
        first="<a href='/index.html?p=1'>首页</a>"
        page_list.append(first)
        if self.current_page==1:
            prev="<a href='#'>上一页</a>"
        else:
            prev="<a href='/index.html?p=%s'>上一页</a>"%self.current_page-1
        page_list.append(prev)
        for i in self.page_num_range():
            temp="<a href='/index.html?p=%s'>%s</a>"%(i,i)
            page_list.append(temp)
        if self.current_page==self.num_pages:
            nex="<a href='#'>下一页</a>"
        else:
            nex="<a href='/index.html?p=%s'>下一页</a>"%self.current_page+1
        page_list.append(nex)
        last="<a href='/index.html?p=%s'>尾页</a>"%self.num_pages
        page_list.append(last)
        return " ".join(page_list)
<!--index.html:-->

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <ul>
    {% for item in posts %}
      <li>{{ item }}</li>
    {% endfor %}
  </ul>
  {{page_obj.page_str|safe}}
  </div>
</body>
</html>
#views.py:

from django.shortcuts import render
from app01.pager import Paginator

L=[]
for i in range(999):
    L.append(i)

def index(req):
    current_page=req.GET.get("p")
    page_obj=Paginator(999,current_page)
    data_list=L[page_obj.start():page_obj.end()]
    return render(req,"index.html",{"data":data_list,"page_obj":page_obj})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值