ORM之自定义分页
ORM之自定义分页
分页是为了在前端展示的时候,数据量过多,导致读取是不方便的问题。
所有我们来实现一下django的分页,并把它写成一个可以在任意django项目中都可用的一个小插件。
分页,其实就是分批次获取数据。
在ORM中获取全部数据后分批次显示数据就是:
models.UserInfo.object.all()[0:10] #取0到10索引值的数据
models.UserInfo.object.all()[10:20] #取10到20索引值的数据
Django自有的分页样例:需要导入 from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage
url中的index
url(r'^index/',views.index)
在view中的index:
1 def index(request): 2 """ 3 分页 4 :param request: 5 :return: 6 """ 7 from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage 8 # for i in range(300): 9 # name = "george" + str(i) 10 # models.UserInfo.objects.create(name=name,age=18,ut_id=1) 11 #这端for循环用一次生成数据即可 12 13 current_page = request.GET.get("page") #取第几页 14 user_list = models.UserInfo.objects.all() 15 paginator = Paginator(user_list,10) 16 #参数的意义,user_list是要分页的数据,10是一页显示的数据量 17 #per_page:每页显示条目数量 18 #count:数据总个数 19 #num_pages:总页数 20 #page_range:总页数的索引范围,如:(1,10),(1,200) 21 #page:page对象 22 try: 23 posts = paginator.page(current_page) #当前显示第几页 24 #has_next: 是否有下一页 25 #next_page_number:下一页页码 26 #has_previous:是否有上一页 27 #previous_page_number:上一页页码 28 #object_list:分页之后的数据列表 29 #number:当前页 30 #paginator:paginator对象 31 except PageNotAnInteger as e: 32 posts = paginator.page(1) 33 except EmptyPage as e: 34 posts = paginator.page(1) 35 return render(request,"index.html",{"posts":posts})
在前端的html:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>index</title> 6 </head> 7 <body> 8 <h1>用户列表</h1> 9 <ul> 10 {% for row in posts.object_list %} 11 <li>{{ row.name }}</li> 12 {% endfor %} 13 </ul> 14 <div> 15 {% if posts.hax_next %} 16 <a href="/index/?page={{ posts.previous_page_number }}">上一页</a> 17 {% endif %} 18 19 {% for num in posts.paginator.page_range %} 20 <a href="/index/?page={{ num }}">{{ num }}</a> 21 {% endfor %} 22 23 {% if posts.hax_next %} 24 <a href="/index/?page={{ posts.next_page_number }}">下一页</a> 25 {% endif %} 26 </div> 27 </body> 28 </html>
django 的自带分页的弊端是只有上下页可以方便的直接使用,但是如果要显示页码的话,django是全部显示的,这要如果数据量大的话,全端会极其不美观,也不便利,但是如果想让其有固定的页面显示长度,就需要二次开发。
Django自定义分页:
url的custom:
url(r'^custom/',views.custom)
在前端的展示样例:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" /> 7 </head> 8 <body> 9 <h1>用户列表</h1> 10 <ul> 11 {% for row in user_list %} 12 <li>{{ row.name }}</li> 13 {% endfor %} 14 </ul> 15 16 <nav aria-label="Page navigation"> 17 <ul class="pagination"> 18 {{ page_info.pager|safe }} 19 </ul> 20 </nav> 21 </body> 22 </html>
最为关键的,创建一个utils包,作为模块使用,文件名为pager.py
1 class PageInfo(object): 2 3 def __init__(self,current_page,all_count,per_page,base_url,show_page=11): 4 """ 5 :param current_page: 表示用户当期想要访问的页码 6 :param all_count: 数据库总行数 7 :param per_page: 每页显示个数 8 :param base_url: 每页显示个数 9 :param show_page: 总共显示多少页码 10 :return: 11 """ 12 try: 13 # 异常处理,页码出现非数字的,返回第一页 14 self.current_page = int(current_page) 15 except Exception as e: 16 # 返回第一页 17 self.current_page = 1 18 19 # 每页显示的个数 20 self.per_page = per_page 21 22 #计算需要的页数,总数据行和每页显示的个数做比例 23 a,b = divmod(all_count,per_page) 24 if b: 25 a = a +1 26 self.all_pager = a 27 self.show_page = show_page 28 self.base_url = base_url 29 def start(self): 30 #每页的起始的数据行 31 return (self.current_page-1) * self.per_page 32 33 def end(self): 34 #每页的结束数据行 35 return self.current_page * self.per_page 36 37 def pager(self): 38 # v = "<a href='/custom.html?page=1'>1</a><a href='/custom.html?page=2'>2</a>" 39 # return v 40 page_list = [] 41 42 #在页码中取一半 43 half = int((self.show_page-1)/2) 44 45 # 如果数据总页数 < 11 46 if self.all_pager < self.show_page: 47 begin = 1 48 stop = self.all_pager + 1 49 # 如果数据总页数 > 11 50 else: 51 # 如果当前页 <=5,永远显示1,11 52 if self.current_page <= half: 53 begin = 1 54 stop = self.show_page + 1 55 else: 56 if self.current_page + half > self.all_pager: 57 begin = self.all_pager - self.show_page + 1 58 stop = self.all_pager + 1 59 else: 60 begin = self.current_page - half 61 stop = self.current_page + half + 1 62 63 if self.current_page <= 1: 64 prev = "<li><a href='#'>上一页</a></li>" 65 else: 66 prev = "<li><a href='%s?page=%s'>上一页</a></li>" %(self.base_url,self.current_page-1,) 67 page_list.append(prev) 68 69 for i in range(begin,stop): 70 if i == self.current_page: 71 #class标签是将当前页加标志色 72 temp = "<li class='active'><a href='%s?page=%s'>%s</a></li>" %(self.base_url,i,i,) 73 else: 74 temp = "<li><a href='%s?page=%s'>%s</a></li>" %(self.base_url,i,i,) 75 page_list.append(temp) 76 77 if self.current_page >= self.all_pager: 78 nex = "<li><a href='#'>下一页</a></li>" 79 else: 80 nex = "<li><a href='%s?page=%s'>下一页</a></li>" %(self.base_url,self.current_page+1,) 81 page_list.append(nex) 82 83 return ''.join(page_list)
在views中代码实现:在custom函数中,就可以from导入utils模块的pager文件的PageInfole类,直接用,给PageInfo传参即可。
1 from utils.pager import PageInfo 2 def custom(request): 3 #总数据的个数 4 all_count = models.UserInfo.objects.all().count() 5 #表示用户当期想要访问的页码 6 current_page = request.GET.get("page") 7 # current_page = int(current_page) 8 #每页显示数据个数 9 # per_page = 10 10 # start = (current_page-1) * per_page 11 # end = current_page * per_page 12 page_info = PageInfo(current_page,all_count,10,"/index/",11) 13 # models.UserInfo.objects.all()[起始位置:结束位置] 14 user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()] 15 16 return render(request,"index.html",{"user_list":user_list,'page_info':page_info})
------------- END -------------