Django-分页
1.Django自带的分页
可以参考:Python之路【第十七篇】:Django【进阶篇 】
你数据量太多的时候页面一下子展示不了,这时就需要用到分页功能。
分批获取数据:
models.UserInfo.objects.all()[0:10] models.UserInfo.objects.all()[10:20]
实际自带的可以这样
在view.py中这样:
#主页 def index(request): #自动分页 current_page = request.GET.get('page') from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage #PageNotAnInteger页面不是整数时;EmptyPage页面是负数 secfile_list = models.anfu.objects.all() #获取全部数据 paginator = Paginator(secfile_list,10) #每10个一页
# per_page: 每页显示条目数量
# count: 数据总个数
# num_pages:总页数
# page_range:总页数的索引范围,如: (1,10),(1,200)
# page: page对象
#增加异常,pagesh是非数字或者负数则跳到第一页 try: posts = paginator.page(current_page)
except PageNotAnInteger as e: posts = paginator.page(1) #.page(n)是第n页 except EmptyPage as e: posts = paginator.page(1)
# has_next 是否有下一页
# next_page_number 下一页页码
# has_previous 是否有上一页
# previous_page_number 上一页页码
# object_list 分页之后的数据列表
# number 当前页
# paginator paginator对象
return render(request, 'index.html', {'posts': posts})
对应到index.html这样:post.object_list
<body> <tbody> {% for row in posts.object_list %} <tr> <td>{{ row.id }}</td> <td>{{ row.CaseName }}</td> </tr> {% endfor %} </tbody> <div> {% if posts.has_previous %} //显示是否有上一页 <a href="/index?page={{ posts.previous_page_number }}">上一页</a> {% endif %} //显示页码范围 {% for num in posts.paginator.page_range %} <a href="/index?page={{ num }}">{{ num }}</a> {% endfor %}
{% if posts.has_next %} //显示是否有下一页 <a href="/index?page={{ posts.next_page_number }}">下一页</a> {% endif %} </div>
注:这个自带的分页只能在Django用,而且有一个弊端就是页码范围会全部显示在页面上,当数目太多就比较难看了。
这时就需要自定义分页了,而且可以将其复用到其他程序~
2.自定义分页组件
def index(request): #分页之自定义分页 #表示用户当前想要访问的页码 current_page = request.GET.get('page') current_page = int(current_page) #每页显示数据个数 per_page = 10 start = (current_page-1) * per_page end = current_page * per_page secfile_list = models.anfu.objects.all()[start:end] return render(request, 'index.html', {'secfile_list': secfile_list})
但问题是代码有点多,页码多了就不好弄了。我们写个类!
#定义一个page类 class PageInfo(object): def __init__(self,current_page,per_page): #异常try,如果用户输入不是数字时,自动跳到page1 try: self.current_page = int(current_page) except Exception as e: self.current_page = 1 self.per_page = per_page #每页显示多少条 def start(self): return (self.current_page-1) * self.per_page def end(self): return self.current_page * self.per_page #主页 def index(request): #分页之自定义分页 #表示用户当前想要访问的页码 current_page = request.GET.get('page')
page_info = PageInfo(current_page,10) secfile_list = models.anfu.objects.all()[page_info.start():page_info.end()] return render(request, 'index.html', {'secfile_list': secfile_list})
类做好了,简化了代码,那下一步怎么显示页码呢?
>>> divmod(101,10) (10, 1) >>> divmod(100,10) (10, 0) #这可以看到,要想知道页数,需要知道总页数
------class里.......
a,b = divmod(all_count,per_page)
if b:
a = a +1
self.all_pager = a
return render(request, 'index.html', {'secfile_list': secfile_list,'page_info':page_info}
在py中的定义,传个函数名它会自动执行;
{{ page_info.pager }}在index.html中实际也会返回,
但默认返回的是 <a href='/index/?page=1'>1</a> ;原因是为防止XSS攻击。
解决方法就是:(就是标记一下这个东西是安全的额,就会显示出来)
{{ page_info.pager |safe }}
#定义一个page类 class PageInfo(object): def __init__(self,current_page,all_count,per_page): """ :param current_page: :param all_count: 数据库总行数 :param per_page: 每页显示的行数 """ #异常try,如果用户输入不是数字时 try: self.current_page = int(current_page) except Exception as e: self.current_page = 1 self.per_page = per_page #每页显示多少条 #分页算术 a, b = divmod(all_count, per_page) if b: a = a + 1 self.all_pager = a def start(self): return (self.current_page-1) * self.per_page def end(self): return self.current_page * self.per_page def pager(self): # v = "<a href='/index/?page=1'>1</a>" # return v page_list =[] for i in range(1,self.all_pager+1): if i == self.current_page: temp = "<a style='display:inline-block;padding:5px;margin:5px;background-color:red;' href='/index/?page=%s'>%s</a>" %(i,i) else: temp = "<a style='display:inline-block;padding:5px;margin:5px' href='/index/?page=%s'>%s</a>" % (i, i) page_list.append(temp) return ''.join(page_list) #把列表中的每个元素都拼接起来 #主页 def index(request): #分页之自定义分页 #表示用户当前想要访问的页码 all_count = models.anfu.objects.all().count() #总页数 current_page = request.GET.get('page') page_info = PageInfo(current_page,all_count,5) secfile_list = models.anfu.objects.all()[page_info.start():page_info.end()] return render(request, 'index.html', {'secfile_list': secfile_list,'page_info':page_info}) ----------html---------- {{ page_info.pager |safe }}
但页面把所有的页面都展示出来了,太多了,我们只想一页展示11个页码:
#定义一个page类 class PageInfo(object): def __init__(self,current_page,all_count,per_page,base_url,show_page): """ :param current_page: :param all_count: 数据库总行数 :param per_page: 每页显示的行数 """ #异常try,如果用户输入不是数字时 try: self.current_page = int(current_page) except Exception as e: self.current_page = 1 self.per_page = per_page #每页显示多少条 #分页算术 a, b = divmod(all_count, per_page) if b: a = a + 1 self.all_pager = a self.show_page = show_page self.base_url = base_url def start(self): return (self.current_page-1) * self.per_page def end(self): return self.current_page * self.per_page def pager(self): # v = "<a href='/index/?page=1'>1</a>" # return v page_list =[] half = int((self.show_page-1)/2) #(11-1)/2=5 #如果数据总页数< 11 if self.all_pager < self.show_page: begin = 1 stop = self.all_pager + 1 #如果总页数 >11 else: if self.current_page <= half: begin = 1 stop = self.show_page + 1 else: if self.current_page + half > self.all_pager: begin = self.all_pager - self.show_page + 1 stop = self.all_pager + 1 else: begin = self.current_page - half stop = self.current_page + half + 1 # begin = self.current_page - half # stop = self.current_page + half +1 #最后一个取不到,再加一 if self.current_page <= 1: prev = "<a style='display:inline-block;padding:5px;margin:5px' href='#'>上一页</a>" else: prev = "<a style='display:inline-block;padding:5px;margin:5px' href='%s?page=%s'>上一页</a>" %(self.base_url,self.current_page-1,) page_list.append(prev) for i in range(begin,stop): if i == self.current_page: temp = "<a style='display:inline-block;padding:5px;margin:5px;background-color:red;' href='%s?page=%s'>%s</a>" %(self.base_url,i,i) else: temp = "<a style='display:inline-block;padding:5px;margin:5px' href='/index/?page=%s'>%s</a>" % (i, i) page_list.append(temp) #下一页 if self.current_page >= self.all_pager: nex = "<a style='display:inline-block;padding:5px;margin:5px' href='#'>下一页</a>" else: nex = "<a style='display:inline-block;padding:5px;margin:5px' href='%s?page=%s'>下一页</a>" %(self.base_url,self.current_page+1,) page_list.append(nex) return ''.join(page_list) #把列表中的每个元素都拼接起来 #主页 def index(request): #去请求的cookie中找凭证;有明文的和带签名的两种方式 #tk = request.COOKIES.get('ticket') tk = request.get_signed_cookie('ticket',default="0",salt='shannon') if tk != "asasasasasaas": return redirect('/login/') else: #去数据库获取数据,(原始的) ##secfile_list = sqlheper.get_list("select id,CaseName,CaseType,Level,Cause,Result from anfu",[]) #secfile_list = models.anfu.objects.all() #return render(request,'index.html',{'secfile_list':secfile_list}) #分页之自定义分页 #表示用户当前想要访问的页码 all_count = models.anfu.objects.all().count() #总页数 current_page = request.GET.get('page') page_info = PageInfo(current_page,all_count,3,'/index',10) secfile_list = models.anfu.objects.all()[page_info.start():page_info.end()] return render(request, 'index.html', {'secfile_list': secfile_list,'page_info':page_info})
增添bootstrap;然后把类单独拿出来,下次用时再
from utils.pager import PageInfo
也就是说新建个utils文件夹并建个pager.py:(一生用起来~)
#!/usr/bin/env python # -*- coding:utf-8 -*- #定义一个page类 class PageInfo(object): def __init__(self,current_page,all_count,per_page,base_url,show_page): """ :param current_page: :param all_count: 数据库总行数 :param per_page: 每页显示的行数 """ #异常try,如果用户输入不是数字时 try: self.current_page = int(current_page) except Exception as e: self.current_page = 1 self.per_page = per_page #每页显示多少条 #分页算术 a, b = divmod(all_count, per_page) if b: a = a + 1 self.all_pager = a self.show_page = show_page self.base_url = base_url def start(self): return (self.current_page-1) * self.per_page def end(self): return self.current_page * self.per_page def pager(self): # v = "<a href='/index/?page=1'>1</a>" # return v page_list =[] half = int((self.show_page-1)/2) #(11-1)/2=5 #如果数据总页数< 11 if self.all_pager < self.show_page: begin = 1 stop = self.all_pager + 1 #如果总页数 >11 else: if self.current_page <= half: begin = 1 stop = self.show_page + 1 else: if self.current_page + half > self.all_pager: begin = self.all_pager - self.show_page + 1 stop = self.all_pager + 1 else: begin = self.current_page - half stop = self.current_page + half + 1 # begin = self.current_page - half # stop = self.current_page + half +1 #最后一个取不到,再加一 if self.current_page <= 1: #应用bootstrap: class='disabled'.. prev = "<li class='disabled'><a href='#'>上一页</a></li>" else: prev = "<li><a href='%s?page=%s'>上一页</a></li>" %(self.base_url,self.current_page-1,) page_list.append(prev) for i in range(begin,stop): if i == self.current_page: temp = "<li class='active'><a href='%s?page=%s'>%s</a></li>" %(self.base_url,i,i) else: temp = "<li><a href='/index/?page=%s'>%s</a></li>" % (i, i) page_list.append(temp) #下一页 if self.current_page >= self.all_pager: nex = "<li class='disabled'><a href='#'>下一页</a>" else: nex = "<li><a href='%s?page=%s'>下一页</a></li>" %(self.base_url,self.current_page+1,) page_list.append(nex) return ''.join(page_list) #把列表中的每个元素都拼接起来
然后再对应的应用就引入views.py:
from utils.pager import PageInfo #主页 def index(request): #去请求的cookie中找凭证;有明文的和带签名的两种方式 #tk = request.COOKIES.get('ticket') tk = request.get_signed_cookie('ticket',default="0",salt='xxxnnon') if tk != "asasasasasaas": return redirect('/login/') else: #去数据库获取数据,(原始的) ##secfile_list = sqlheper.get_list("select id,CaseName,CaseType,Level,Cause,Result from anfu",[]) #secfile_list = models.anfu.objects.all() #return render(request,'index.html',{'secfile_list':secfile_list}) #分页之自定义分页 #表示用户当前想要访问的页码 all_count = models.anfu.objects.all().count() #总页数 current_page = request.GET.get('page') page_info = PageInfo(current_page,all_count,6,'/index',10) secfile_list = models.anfu.objects.all()[page_info.start():page_info.end()] return render(request, 'index.html', {'secfile_list': secfile_list,'page_info':page_info})
再传入html:
<nav aria-label="Page navigation"> <ul class="pagination pagination-sm"> {{ page_info.pager |safe }} </ul> </nav>
ethtool
为美好的生活奋斗!