Django 之 分页和序列化
正文
分页
一、Django内置分页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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 ( 'page' ) # 通过 get 请求得到当前请求的页数 paginator = Paginator(L, 10) # 实例化传入俩个参数(所有数据,当页显示条数) # per_page: 每页显示条目数量 # count: 数据总个数 # num_pages:总页数 # page_range:总页数的索引范围,如: (1,10),(1,200) # page: page对象 try : posts = paginator.page(current_page)# 传入当前页码,观源码可得实例化了一个Page对象 # has_next 是否有下一页 # next_page_number 下一页页码 # has_previous 是否有上一页 # previous_page_number 上一页页码 # object_list 分页之后的数据列表 # number 当前页 # paginator paginator对象 except PageNotAnInteger: # 不是数字 posts = paginator.page(1) except EmptyPage: # 超出页码范围 posts = paginator.page(paginator.num_pages) return render(request, 'index.html' , { 'posts' : posts}) # posts封装了一些方法 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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= "?p={{ posts.previous_page_number }}" >上一页</a> {% endif %} <span class = "current" > Page {{ posts.number }} of {{ posts.paginator.num_pages }}. </span> {% if posts.has_next %} <a href= "?p={{ posts.next_page_number }}" >下一页</a> {% endif %} </span> </div> </body> </html> |
那么、Django的内置分页基本俩个类实现、并封装了一些方法来使用、此时并不能满足有一些的需求
二、Django内置分页的拓展
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 拓展内置分页views.py from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger user = [] for i in range(1, 1001): dic = { 'name' : 'root' + str(i), 'pwd' : i} user.append(dic) class DiyPaginator(Paginator): def __init__(self, current_page,max_pager_num, *args, **kwargs): "" " :param current_page: 当前页码 :param max_pager_num: 显示页码个数的最大值 :param args: :param kwargs: "" " self.current_page = int (current_page) self.max_pager_num = int (max_pager_num) super(DiyPaginator,self).__init__(*args,**kwargs) def pager_num_range(self): # 需要的参数 # 当前页码 self.current_page # 页码数量 self.max_pager_num # 总页数 self.num_pages # 如果总页数小于页码个数最大值的情况 if self.num_pages < self.max_pager_num: return range(1,self.num_pages+1) # 返回 从 1 到 总页数 # 如果总页数大于页码数量且当前所选页码小于页码数量的一半 part = self.max_pager_num //2 if self.current_page <= part: return range(1,self.max_pager_num+1) # 返回 从 1 到 页码个数最大值 # 如果当前页码加一半的页码 大于 总页数 if (self.current_page+part) > self.num_pages: # 返回 从总页数-最大页码数 到 总页数 range的用法在此不作解释 # 例如 96页+5页 超出总页数 则返回的范围是 从 总页数-最大页码数量+1 到 总页数+1 return range(self.num_pages-self.max_pager_num+1,self.num_pages+1) # 其余情况从 当前页码减去显示页码的平均值开始 到 当前页码加显示页码的平均值(并加一)结束 return range(self.current_page-part,self.current_page+part+1) def index(request): p = request.GET. get ( 'page' ) start = ( int (p)-1)*10 end = int (p)*10 data = user[start:end] return render(request, 'index.html' ,{ 'data' :data, 'user' :user}) def index1(request): current_page = request.GET. get ( 'page' ) paginator = DiyPaginator(current_page, 9, user, 10) # Paginator所封装的方法 # per_page: 每页显示条目数量 # count: 数据总个数 # num_pages:总页数 # page_range:总页数的索引范围,如: (1,10),(1,200) # page: page对象 try : posts = paginator.page(current_page) # has_next 是否有下一页 # next_page_number 下一页页码 # has_previous 是否有上一页 # previous_page_number 上一页页码 # object_list 分页之后的数据列表 # number 当前页 # paginator paginator对象 except PageNotAnInteger: # 不是整形数字 posts = paginator.page(1) except EmptyPage: # 如果是空值 posts = paginator.page(paginator.num_pages) return render(request, 'index1.html' ,{ 'posts' :posts}) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 拓展内置分页HTML <!DOCTYPE html> <html lang= "en" > <head> <meta charset= "UTF-8" > <title>Title</title> </head> <body> <ul> {% for row in posts.object_list %} <li>{{ row.name }}-{{ row.pwd }}</li> {% endfor %} </ul> {% include 'include/pager.html' %} </body> </html> ################################## include 组件代码 {% if posts.has_previous %} <a href= "/index1?page={{ posts.previous_page_number }}" >上一页</a> {% endif %} {% for num in posts.paginator.pager_num_range %} {% if num == posts.number %} <a style= "color: red;font-size: 20px" href= "/index1?page={{ num }}" >{{ num }}</a> {% else %} <a href= "/index1?page={{ num }}" >{{ num }}</a> {% endif %} {% endfor %} {% if posts.has_next %} <a href= "/index1?page={{ posts.next_page_number }}" >下一页</a> {% endif %} <span> 当前页:{{ posts.number }} 总页数:{{ posts.paginator.num_pages }} </span> |
三、自定义分页(适用于任何地方)
- 创建处理分页数据的类
- 根据分页数据获取数据
- 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]或者额外的作出一些拓展也可以
创建处理分页数据的类时,大致也需要四个参数(详情观看类构造方法)
1、为了减少服务器内存的负载,不再获取所有数据的,而是获得所有数据的总个数,然后再根据索引查数据库的内容
2、当前页码
3、每页显示的行数
4、页码显示的数量
对于页数的显示大致也可以归类为三种情况(详情观看类中page_num_range函数)
1、计算的总页数小于页码显示的数量
2、计算的总页数大于页码显示的数量
A、当前页数小于页码数量的一半
B、当前页数加页码数量的一半超出总页数的范围
3、正常情况
从 当前页数 减 一半页码数量 到 当前页数 加 一半页码数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | 自定义分页 class Pagination( object ): def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=9): "" " :param totalCount: 所有数据总个数 :param currentPage: 当前页数 :param perPageItemNum: 每页显示行数 :param maxPageNum: 最多显示页码个数 "" " self.total_count = totalCount # 对当前的页码进行一次异常捕获 try : currentPage = int (currentPage) if currentPage <= 0: currentPage = 1 self.current_page = currentPage except Exception: self.current_page = 1 self.per_page_item_num = perPageItemNum self.max_page_num = maxPageNum @property def start(self): # 数据索引开始的值 return (self.current_page-1) * self.per_page_item_num @property def end(self): # 数据索引结束的值 return self.current_page * self.per_page_item_num @property def num_pages(self): "" " 总页数 : return : "" " # 得商取余得内置函数 x, o = divmod(self.total_count,self.per_page_item_num) if o == 0: return x return x + 1 @property def page_num_range(self): if self.num_pages < self.max_page_num: return range(1, self.num_pages+1) part = 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-self.max_page_num+1, self.num_pages+1) return range(self.current_page-part, self.current_page+part+1) def page_str(self): page_list = [] first = "<li><a href='/index2/?page=1'>首页</a></li>" page_list.append(first) if self.current_page == 1: prev_page = "<li><a href='#'>上一页</a></li>" else : prev_page = "<li><a href='/index2/?page=%s'>上一页</a></li>" %(self.current_page-1) page_list.append(prev_page) for i in self.page_num_range: if i == self.current_page: temp = "<li class='active'><a href='/index2/?page=%s'>%s</a></li>" %(i,i) else : temp = "<li><a href='/index2/?page=%s'>%s</a></li>" % (i, i) page_list.append(temp) if self.current_page == self.num_pages: next_page = "<li><a href='#'>下一页</a></li>" else : next_page = "<li><a href='/index2/?page=%s'>下一页</a></li>" %(self.current_page+1) page_list.append(next_page) last = "<li><a href='/index2/?page=%s'>尾页</a></li>" %self.num_pages page_list.append(last) return '' . join (page_list) |
1 2 3 4 5 6 7 8 9 10 11 | 自定义分页views.py def index2(request): from page.diypage import Pagination current_page = request.GET. get ( 'page' ) page_obj = Pagination(1000,current_page) data_list = user[page_obj.start:page_obj.end] return render(request, 'index2.html' ,{ 'data' : data_list, 'page_obj' : page_obj }) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 自定义分页HTML # 本页面引用了bootstrap样式 <!DOCTYPE html> <html lang= "en" > <head> <meta charset= "UTF-8" > <title>Title</title> <link rel= "stylesheet" href= "/static/bootstrap/css/bootstrap.css" /> </head> <body> <ul> {% for row in data %} <li>{{ row.name }}-{{ row.pwd }}</li> {% endfor %} </ul> {% for i in page_obj.pager_num_range %} <a href= "/index2/?page={{ i }}" >{{ i }}</a> {% endfor %} <hr/> <ul class = "pagination pagination-sm" > {{ page_obj.page_str|safe }} </ul> <div style= "height: 300px;" ></div> </body> </html> |
序列化
序列化是将对象状态转换为可保持或传输的格式的过程
反序列化是指将存储在存储媒体中的对象状态装换成对象的过程
例如游戏都有存档的功能、再次开始的时候只需读档即可(这即是一个序列化与反序列的过程)
序列化也可以将一个对象传递到另一个地方的
关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。
1、serializers
1 2 3 4 5 | from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize( "json" , ret) |
2、json.dumps
1 2 3 4 5 6 7 8 | import json #ret = models.BookType.objects.all().values('caption') ret = models.BookType.objects.all().values_list( 'caption' ) ret=list(ret) result = json.dumps(ret) |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步