一.内置分页
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})