上一篇:Django之cookie详解与实战示例(其他篇三)点击跳转
目录篇:Django之其他目录篇 点击跳转
下一篇:Django之session详解与实战示例(其他篇五)点击跳转
目录
分页的作用
假如数据有上百万条,我们不可能让前端把所有的数据显示,如果100个用户同时访问,就是上亿条数据,所以我们需要进行分页显示
自定义通用分页插件需求分析
1.数据总长度count
2.根据显示的数量获取页码总数量page_count:
count/ amount_of_data_displayed_for_per_page + 余数(remainder)算1页 (生成标签页码数量)
Python计算余数:x,y=divmod(10,3) # 10/3 =3 + 1 x=3 + y=1 == 4
3. data_displayed_for_per_page _get_by_index:
[start(页码-1)*显示数量:end(页码*显示的数量)]
假如点击页码1 1-1*7=0 1*7 数据[0:7]
4.根据当前页码(current_page)+自定义显示页码数量 生成要显示的页码标签数量:
start_index= None
end_index= None
假如要显示11个页码标签
点击当前页码15,start_index=15-5=10 end_index=15+5=20
5.当前的页码标签需要加颜色
6.进行判断如果点击页码标签为6以下,或者点击最后一个页码标签,页码标签数量显示应该固定固定11 ,且总数据页码数量不足11的时候显示正常数量
7.增加上一页标签和下一页标签且第一页点击上一页标签和最后一页点击下一页标签是无反应或者不给点击
8.inpurt搜索的页码,点击GO跳到指定页码,判断输入页码的方范围,超过页码总数量或者少于1的时候不给与跳转进行提示
9.配合前端基于cookie是可以让用户进行选择要显示的数据数量
10.配合编辑数据后的跳转,应该跳转编辑数据所在的页码
11.具备通用性
实战自定义通用分页插件cookie实现用户可选每页内容显示数量
当然自己写的前端标签显示没有写那么好看,其实前端基本现在一般都是使用bootstarp,如果觉得不好看,可自行引入bootstarp分页标签
1.创建Django项目
Django之创建项目【二】:https://blog.csdn.net/Burgess_zheng/article/details/86505526
2.定义setting配置文件的静态目录路径和创建静态目录
路径:project_burgess/project_burgess/setting
cookie.js:我们需要在前端获取用户选择的每页显示数量
3.定义请求的URL路由分发
路径:project_burgess/project_burgess/urls.py
from django.contrib import admin from django.urls import path,re_path #Django版本2.0以上 from project_burgess import views from django.conf.urls import url #Django2.0 from django.conf.urls import include urlpatterns = [ path('admin/', admin.site.urls), # page+cookies path('bur_page/', views.bur_page), # 最新版本的Django路由使用path # url(r'^bur_page/', views.bur_page), #2.0版本使用的是url ]
4.定义通用page插件
路径:project_burgess/backend/pagination.py.py
__author__ = "Burgess Zheng" #!/usr/bin/env python #-*- coding:utf-8 -*- from django.utils.safestring import mark_safe # 该模块可以让字符串转换成标签形式 class Page: def __init__(self,current_page,data_count,per_page_count=10,page_num=7): self.current_page = current_page #实例化的对象传进来的当前页码形参 self.data_count = data_count #实例化的对象传进来的索引长度形参 self.per_page_count = per_page_count #实例化的对象如果不传参,默认显示每个页码显示10个索引, self.page_num = page_num #实例化的对象如果不传参,默认显示7个页码 def start(self): return (self.current_page-1)* self.per_page_count #返回实例化的时候传进来的当前页码-1*实例化的时候传进来每个页码显示的索引 def end(self): return self.current_page * self.per_page_count #返回实例化的时候传进来的当前页码*实例化的时候传进来每个页码显示的索引 @property #这样其他调用all_connt()方法就无需() def all_count(self): v,y = divmod(self.data_count,self.per_page_count) #divmod(总索引数,每页显示的索引数) 得到的结果:(总索引数除以每页索引数=数字,余数) if y: v += 1 return v #返回多少个页码数量 def page_str(self,base_url): page_list = [] if self.all_count < self.page_num: start_index = 1 end_index = self.all_count + 1 else: if self.current_page <= (self.page_num + 1) / 2: start_index = 1 end_index = self.page_num + 1 else: start_index = self.current_page - (self.page_num - 1) / 2 end_index = self.current_page + (self.page_num + 1) / 2 if (self.current_page + (self.page_num - 1) / 2) > self.all_count: end_index = self.all_count + 1 start_index = self.all_count - self.page_num + 1 if self.current_page == 1: # 下面3条都可以,反正没加入列表,后台调用不到 prev = '<a class="page" href="javascript:void(0)">上一页</a>' # prev = '<a class="page" href="#">上一页</a>' # pass else: prev = '<a class="page" href="%s?p=%s">上一页</a>' %(base_url,self.current_page - 1,) page_list.append(prev) for i in range(int(start_index), int(end_index)): # start_index=1 end_index=16 range(1,16) i = 1到15 if i == self.current_page: # 客户的请求信息是6的话 标签加上active temp = '<a class="page active" href="%s?p=%s">%s</a>' %(base_url,i, i) else: temp = '<a class="page" href="%s?p=%s">%s</a>' %(base_url,i, i) # 第一个%s变量=i 第二个%s变量=i page_list.append(temp) if self.current_page == self.all_count: nex = '<a class="page" href="javascript:void(0)">下一页</a>' else: nex = '<a class="page" href="%s?p=%s">下一页</a>' %(base_url,self.current_page + 1) page_list.append(nex) jump = """ <input type='text' /><a onclick='jumpTo(this,"%s?p=");'>GO</a> <script> function jumpTo(ths,base){ var val = ths.previousSibling.value; location.href = base + val; } </script> """%(base_url,) page_list.append(jump) from django.utils.safestring import mark_safe # 该模块可以让字符串转换成标签形式 page_str = mark_safe("".join(page_list)) # 列表的字符串进行拼接 ":"以冒号拼接 ""无间隔拼接 return page_str
5.定义url对应函数(引入自定义的通用page插件)
路径:project_burgess/project_burgess/views.py
from backend import pagination LIST = [] for i in range(1009): #i = 0到108 LIST.append(i) def bur_page(request): current_page = request.GET.get('p',1) current_page = int(current_page) val_count = request.COOKIES.get('per_page_count',10)#获取cookie的key为per_page_count的值 #因为第一次登录由于没有该per_page_count的cookies值,所以是none,如果是none就赋值10 val_count = int(val_count)#如果是用户cookies选择的显示值 是字符串所以需要转程数字类型 page_obj = pagination.Page(current_page,len(LIST),val_count) #实例化一个对象 data = LIST[page_obj.start():page_obj.end()] #如果不想调取对象基于的类的方法带括号,可以在该方法上面一行装饰一个参数@property page_str = page_obj.page_str("/bur_page/") return render(request,'bur_page.html',{'li':data,'page_str':page_str})
6.定义响应的html文件
路径:project_burgess/templates/bur_page.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .pagination .page{ display: inline-block; padding:5px; background-color: aqua; margin: 5px; } .pagination .active{ background-color:brown; color: white; } </style> </head> <body> <ul> {% for item in li %} <li>{{ item }}</li> {% endfor %} </ul> <div> <select id="ps" onchange="changePageSize(this)"> <option value="10">10</option> <option value="30">30</option> <option value="50">50</option> <option value="100">100</option> </select> </div> <div class="pagination"> {{ page_str }} </div> <script src="/static/jquery.min.js"></script> <script src="/static/jquery.cookie.js"></script> <script> $(function () { var v = $.cookie('per_page_count'); $('#ps').val(v); }); function changePageSize(ths) { var v = $(ths).val(); console.log(v); $.cookie('per_page_count',v); location.reload() } </script> </body> </html>
7.启动Django
手动:python manage.py runserver 127.0.0.1:8000
pycharm:
8.浏览器访问URL结果
get请求index
随便选择1页
选择框选择每页显示30
当然这个自己写的自定义分页插件还有那么一点需要补充:
如前端显示非常难看,通用page插件写html标签引入bootstrap的标签解决了
如跳转的时候跳转到N页(该页没数据,其实我们在通用page插件内写个判断就OK了)
都是小问题,自己补下就行了
Django自带的分页功能
写自定义分页其实是多余的....当做锻炼思维把,其实django就自带了分页功能我们直接应用就行了
Django框架(官网描述:https://docs.djangoproject.com/en/2.1/topics/pagination/)里面有完整示例
注释:
完整示例
后端
注意: contact_list = contacts.objects.all() #只是生成对象,并没有取数据。不然这示例就跟没分页似
前端
使用终端python命令实战效果
#插入:实验Django分页参数(使用终端cmd) >>> from django.core.paginator import Paginator >>> querysets = ['Burgess','Cristal','Son','Dauter','Mendou'] >>> querysets = Paginator(querysets,2) #每个页2条数据 >>> querysets.count #计算数据总数量 5 >>> querysets.num_pages #计算总页数 3 >>> querysets.page_range #总页数的range范围 range(1,4) 循环出来不包含4 range(1, 4) >>> querysets = querysets.page(2) #实例化第2页的数据对象 >>> querysets #当前页是第2页,总数3页 <Page 2 of 3> >>> querysets.number #获取该对象的页码 2 >>> querysets.has_next() #当前页(第2页)下一页是否存在 True >>> querysets.object_list #获取当前页的数据 ['Son', 'Dauter'] >>> querysets.page_range #取页码总数量的range范围,但是由于实例化第2页数据成为对象的名字覆盖了之前的对象名字所以报错,但是我还是需要根据该第2页对象进行获取总页码数量的range范围 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Page' object has no attribute 'page_range' >>> dir(querysets) #querysets是第二页数据的实例化对象(查看该对象的所有参数) ['__abstractmethods__', '__class__', '__contains__', '__delattr__', '__dict__', '__dir__', '__doc__' , '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init __', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__ reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__su bclasshook__', '__weakref__', '_abc_cache', '_abc_negative_cache', '_abc_negative_cache_version', '_ abc_registry', 'count', 'end_index', 'has_next', 'has_other_pages', 'has_previous', 'index', 'next_p age_number', 'number', 'object_list', 'paginator', 'previous_page_number', 'start_index'] #可根据第2页对象的参数paginator获取继承的对象,然后进行获取总页数的range 范围 >>> querysets.paginator #获取继承的对象 <django.core.paginator.Paginator object at 0x00000000011C3748> >>> querysets.paginator.page_range #获取总页数的range 范围 range(1, 4) >>> for i in querysets.paginator.page_range: ... print(i) ... 1 2 3
实战Django自带的分页功能+cookie实现用户可选每页内容显示数量
定义url对应函数(引入自定义的通用page插件)
路径:project_burgess/project_burgess/views.py
LIST = [] for i in range(1009): #i = 0到108 LIST.append(i) def bur_page(request): current_page = request.GET.get('p',1) current_page = int(current_page) val_count = request.COOKIES.get('per_page_count',10)#获取cookie的key为per_page_count的值 from django.core.paginator import Paginator data = Paginator(LIST, val_count)#过滤后进行分页,每页显示数据数量 data = data.get_page(current_page) #根据页码获取该页数据数据 return render(request,'bur_page.html',{'data':data})
定义响应的html文件
路径:project_burgess/templates/bur_page.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style></style> </head> <body> <ul> {% for item in data %} <li>{{ item }}</li> {% endfor %} </ul> <div> <select id="ps" onchange="changePageSize(this)"> <option value="10">10</option> <option value="30">30</option> <option value="50">50</option> <option value="100">100</option> </select> </div> <div class="pagination"> <span class="step-links"> {% if data.has_previous %} <a href="?p=1">« 首页</a> <a href="?p={{ data.previous_page_number }}">上一页</a> {% endif %} <span class="current"> Page {{ data.number }} of {{ data.paginator.num_pages }}. </span> {% if data.has_next %} <a href="?p={{ data.next_page_number }}">下一页</a> <a href="?p={{ data.paginator.num_pages }}">尾页»</a> {% endif %} </span> </div> <script src="/static/jquery.min.js"></script> <script src="/static/jquery.cookie.js"></script> <script> $(function () { var v = $.cookie('per_page_count'); $('#ps').val(v); }); function changePageSize(ths) { var v = $(ths).val(); console.log(v); $.cookie('per_page_count',v); location.reload() } </script> </body> </html>
浏览器访问URL结果
点击下一页
现在显示数量
觉得丑是不是?还是老样子引入bootstrap的标签就OK(就不实验了),以下以前实验的项目引用bootstrap分页后的效果
上一篇:Django之cookie详解与实战示例(其他篇三)点击跳转
目录篇:Django之其他目录篇 点击跳转
下一篇:Django之session详解与实战示例(其他篇五)点击跳转