Django-进阶 分页,中间件
分页
Django的分页器(paginator)
view

- from django.shortcuts import render,HttpResponse
- # Create your views here.
- from app01.models import *
- from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
- def index(request):
- '''
- 批量导入数据:
- Booklist=[]
- for i in range(100):
- Booklist.append(Book(title="book"+str(i),price=30+i*i))
- Book.objects.bulk_create(Booklist)
- '''
- '''
- 分页器的使用:
- book_list=Book.objects.all()
- paginator = Paginator(book_list, 10)
- print("count:",paginator.count) #数据总数
- print("num_pages",paginator.num_pages) #总页数
- print("page_range",paginator.page_range) #页码的列表
- page1=paginator.page(1) #第1页的page对象
- for i in page1: #遍历第1页的所有数据对象
- print(i)
- print(page1.object_list) #第1页的所有数据
- page2=paginator.page(2)
- print(page2.has_next()) #是否有下一页
- print(page2.next_page_number()) #下一页的页码
- print(page2.has_previous()) #是否有上一页
- print(page2.previous_page_number()) #上一页的页码
- # 抛错
- #page=paginator.page(12) # error:EmptyPage
- #page=paginator.page("z") # error:PageNotAnInteger
- '''
- book_list=Book.objects.all()
- paginator = Paginator(book_list, 10)
- page = request.GET.get('page',1)
- currentPage=int(page)
- try:
- print(page)
- book_list = paginator.page(page)
- except PageNotAnInteger:
- book_list = paginator.page(1)
- except EmptyPage:
- book_list = paginator.page(paginator.num_pages)
- return render(request,"index.html",{"book_list":book_list,"paginator":paginator,"currentPage":currentPage})

index.html:

- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">- </head>
- <body>
- <div class="container">
- <h4>分页器</h4>
- <ul>
- {% for book in book_list %}
- <li>{{ book.title }} -----{{ book.price }}</li>
- {% endfor %}
- </ul>
- <ul class="pagination" id="pager">
- {% if book_list.has_previous %}
- <li class="previous"><a href="/index/?page={{ book_list.previous_page_number }}">上一页</a></li>
- {% else %}
- <li class="previous disabled"><a href="#">上一页</a></li>
- {% endif %}
- {% for num in paginator.page_range %}
- {% if num == currentPage %}
- <li class="item active"><a href="/index/?page={{ num }}">{{ num }}</a></li>
- {% else %}
- <li class="item"><a href="/index/?page={{ num }}">{{ num }}</a></li>
- {% endif %}
- {% endfor %}
- {% if book_list.has_next %}
- <li class="next"><a href="/index/?page={{ book_list.next_page_number }}">下一页</a></li>
- {% else %}
- <li class="next disabled"><a href="#">下一页</a></li>
- {% endif %}
- </ul>
- </div>
- </body>
- </html>

扩展

- def index(request):
- book_list=Book.objects.all()
- paginator = Paginator(book_list, 15)
- page = request.GET.get('page',1)
- currentPage=int(page)
- # 如果页数十分多时,换另外一种显示方式
- if paginator.num_pages>30:
- if currentPage-5<1:
- pageRange=range(1,11)
- elif currentPage+5>paginator.num_pages:
- pageRange=range(currentPage-5,paginator.num_pages+1)
- else:
- pageRange=range(currentPage-5,currentPage+5)
- else:
- pageRange=paginator.page_range
- try:
- print(page)
- book_list = paginator.page(page)
- except PageNotAnInteger:
- book_list = paginator.page(1)
- except EmptyPage:
- book_list = paginator.page(paginator.num_pages)
- return render(request,"index.html",locals())

自定义分页器

- """
- 分页组件使用示例:
- obj = Pagination(request.GET.get('page',1),len(USER_LIST),request.path_info)
- page_user_list = USER_LIST[obj.start:obj.end]
- page_html = obj.page_html()
- return render(request,'index.html',{'users':page_user_list,'page_html':page_html})
- """
- class Pagination(object):
- def __init__(self,current_page,all_count,base_url,per_page_num=2,pager_count=11):
- """
- 封装分页相关数据
- :param current_page: 当前页
- :param all_count: 数据库中的数据总条数
- :param per_page_num: 每页显示的数据条数
- :param base_url: 分页中显示的URL前缀
- :param pager_count: 最多显示的页码个数
- """
- try:
- current_page = int(current_page)
- except Exception as e:
- current_page = 1
- if current_page <1:
- current_page = 1
- self.current_page = current_page
- self.all_count = all_count
- self.per_page_num = per_page_num
- self.base_url = base_url
- # 总页码
- all_pager, tmp = divmod(all_count, per_page_num)
- if tmp:
- all_pager += 1
- self.all_pager = all_pager
- self.pager_count = pager_count
- self.pager_count_half = int((pager_count - 1) / 2)
- @property
- def start(self):
- return (self.current_page - 1) * self.per_page_num
- @property
- def end(self):
- return self.current_page * self.per_page_num
- def page_html(self):
- # 如果总页码 < 11个:
- if self.all_pager <= self.pager_count:
- pager_start = 1
- pager_end = self.all_pager + 1
- # 总页码 > 11
- else:
- # 当前页如果<=页面上最多显示11/2个页码
- if self.current_page <= self.pager_count_half:
- pager_start = 1
- pager_end = self.pager_count + 1
- # 当前页大于5
- else:
- # 页码翻到最后
- if (self.current_page + self.pager_count_half) > self.all_pager:
- pager_end = self.all_pager + 1
- pager_start = self.all_pager - self.pager_count + 1
- else:
- pager_start = self.current_page - self.pager_count_half
- pager_end = self.current_page + self.pager_count_half + 1
- page_html_list = []
- first_page = '<li><a href="%s?page=%s">首页</a></li>' % (self.base_url,1,)
- page_html_list.append(first_page)
- if self.current_page <= 1:
- prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
- else:
- prev_page = '<li><a href="%s?page=%s">上一页</a></li>' % (self.base_url,self.current_page - 1,)
- page_html_list.append(prev_page)
- for i in range(pager_start, pager_end):
- 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="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
- page_html_list.append(temp)
- if self.current_page >= self.all_pager:
- next_page = '<li class="disabled"><a href="#">下一页</a></li>'
- else:
- next_page = '<li><a href="%s?page=%s">下一页</a></li>' % (self.base_url,self.current_page + 1,)
- page_html_list.append(next_page)
- last_page = '<li><a href="%s?page=%s">尾页</a></li>' % (self.base_url,self.all_pager,)
- page_html_list.append(last_page)
- return ''.join(page_html_list)

中间件
中间件的概念
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。
Django的中间件的定义:
1
|
Middleware is a framework of hooks into Django’s request / response processing. <br>It’s a light, low - level “plugin” system for globally altering Django’s input or output. |
如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。
可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现。
大家可能频繁在view使用request.user
吧。 Django想在每个view执行之前把user设置为request的属性,于是就用了一个中间件来实现这个目标。所以Django提供了可以修改request 对象的中间件 AuthenticationMiddleware
。
Django默认的Middleware
:

- MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
- ]

每一个中间件都有具体的功能。
自定义中间件
中间件中一共有四个方法:

- process_request
- process_view
- process_exception
- process_response

process_request,process_response
当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。
上述截图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin
需要导入
1
|
from django.utils.deprecation import MiddlewareMixin |
in views:
- def index(request):
- print("view函数...")
- return HttpResponse("OK")
in Mymiddlewares.py:

- from django.utils.deprecation import MiddlewareMixin
- from django.shortcuts import HttpResponse
- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- class Md2(MiddlewareMixin):
- def process_request(self,request):
- print("Md2请求")
#return HttpResponse("Md2中断")- def process_response(self,request,response):
- print("Md2返回")
- return response

结果:
- Md1请求
- Md2请求
- view函数...
- Md2返回
- Md1返回
注意:如果当请求到达请求2的时候直接不符合条件返回,即return HttpResponse("Md2中断"),程序将把请求直接发给中间件2返回,然后依次返回到请求者,结果如下:
返回Md2中断的页面,后台打印如下:
- Md1请求
- Md2请求
- Md2返回
- Md1返回
流程图如下:
process_view
1
|
process_view( self , request, callback, callback_args, callback_kwargs) |
Mymiddlewares.py修改如下

- from django.utils.deprecation import MiddlewareMixin
- from django.shortcuts import HttpResponse
- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- #return HttpResponse("Md1中断")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("Md1view")
- class Md2(MiddlewareMixin):
- def process_request(self,request):
- print("Md2请求")
- return HttpResponse("Md2中断")
- def process_response(self,request,response):
- print("Md2返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("Md2view")

结果如下:

- Md1请求
- Md2请求
- Md1view
- Md2view
- view函数...
- Md2返回
- Md1返回

下图进行分析上面的过程:
当最后一个中间的process_request到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户。
process_view可以用来调用视图函数:

- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- #return HttpResponse("Md1中断")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- # return HttpResponse("hello")
- response=callback(request,*callback_args,**callback_kwargs)
- return response

结果如下:
- Md1请求
- Md2请求
- view函数...
- Md2返回
- Md1返回
注意:process_view如果有返回值,会越过其他的process_view以及视图函数,但是所有的process_response都还会执行。
process_exception
1
|
process_exception( self , request, exception) |
示例修改如下:

- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- #return HttpResponse("Md1中断")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- # return HttpResponse("hello")
- # response=callback(request,*callback_args,**callback_kwargs)
- # return response
- print("md1 process_view...")
- def process_exception(self):
- print("md1 process_exception...")
- class Md2(MiddlewareMixin):
- def process_request(self,request):
- print("Md2请求")
- # return HttpResponse("Md2中断")
- def process_response(self,request,response):
- print("Md2返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("md2 process_view...")
- def process_exception(self):
- print("md1 process_exception...")

结果如下:

- Md1请求
- Md2请求
- md1 process_view...
- md2 process_view...
- view函数...
- Md2返回
- Md1返回

流程图如下:
当views出现错误时:
将md2的process_exception修改如下:
- def process_exception(self,request,exception):
- print("md2 process_exception...")
- return HttpResponse("error")
结果如下:

- Md1请求
- Md2请求
- md1 process_view...
- md2 process_view...
- view函数...
- md2 process_exception...
- Md2返回
- Md1返回

Django-进阶 分页,中间件的更多相关文章
- Django进阶之中间件
中间件简介 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在djang ...
- Django 进阶(分页器&中间件)
分页 Django的分页器(paginator) view from django.shortcuts import render,HttpResponse # Create your views h ...
- Python Django的分页,Form验证,中间件
本节内容 Django的分页 Form 中间件 1 Django 分页 1.1 Django自带的分页 1.首先来看下我的测试数据环境 ############ models.py ######### ...
- Django进阶(路由系统、中间件、缓存、Cookie和Session、Ajax发送数据
路由系统 1.每个路由规则对应一个view中的函数 url(r'^index/(\d*)', views.index), url(r'^manage/(?P<name>\w*)/(?P&l ...
- Django【进阶】中间件
中间件 一.概念 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 其 ...
- Python之路,Day16 - Django 进阶
Python之路,Day16 - Django 进阶 本节内容 自定义template tags 中间件 CRSF 权限管理 分页 Django分页 https://docs.djangoproj ...
- python web框架 Django进阶
django 进阶 基础中,一些操作都是手动创建连接的非主流操作,这样显得太low,当然也是为了熟悉这个框架! 实际中,django自带连接数据库和创建app的机制,同时还有更完善的路由系统机制.既然 ...
- Django进阶2
一.ORM操作进阶 ForeignKey关联 示例models from django.db import models # Create your models here. class User(m ...
- Django进阶篇【1】
注:本篇是Django进阶篇章,适合人群:有Django基础,关于Django基础篇,将在下一章节中补充! 首先我们一起了解下Django整个请求生命周期: Django 请求流程,生命周期: 路由部 ...
- Django进阶知识
drf学习之Django进阶点 一.Django migrations原理 1.makemigrattions: 相当于在每个app下的migrations文件夹下生成一个py脚本文件用于创建表或则修 ...
随机推荐
- lua调试小技巧
lua中,如果碰到某个属性值改变了,但是修改的地方又特别多,调试就特别麻烦了,有个小技巧,直接贴代码 local m = { __index = function( t, k ) ...
- webdriver与JS操作浏览器元素
1.JQuery的选择器实例 语法 描述 $(this) 当前 HTML 元素 $("p") 所有 <p> 元素 $("p.intro") 所有 c ...
- 正则表达式备忘(基于JavaScript)
基于JS学习的正则表达式 备忘 e.g.匹配以0开头的三位或四位区号,以-分格的7或8位电话号码var reg1 = /^0\d{2,3}\-\d{7,8}$/;或var reg1 = new Reg ...
- 转 Hadoop傻瓜化:Datameer大数据收入翻三番
淘薛奎发布到 <数据极客> 06-28 16:04 随着分析正在成为企业IT的核心,昔日的BI- ETL-EDW分析范型已经完全落伍,不再适用.而力推“大数据傻瓜化”的Datameer ...
- 每天一个Linux命令(34)grep命令
grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具 ...
- unigui中TUniDBEdit的OnEndDrag问题
非常奇怪,unigui中TUniDBEdit未发布OnEndDrag属性,包括其子类:TUniDBNumberEdit.TUniDBFormattedNumberEdit.而其他数据感知组件都有OnE ...
- intel dpdk api interrupt module 中断模块介绍
声明:此文档只做学习交流使用,请勿用作其他商业用途 author:朝阳_tonyE-mail : linzhaolover@gmail.comCreate Date: 2013-7-12 11:46: ...
- HTML5坦克大战1
在JavaScript中,不要在变量为定义之前去使用,这样很难察觉并且无法运行. 颜色不对. 当我的坦克移动时,敌人坦克消失. tankGame3.html <!DOCTYPE html> ...
- js 格式华货币
/*货币格式化*/ function formatMoney(num) { num = num.toString().replace(/\$|\,/g,''); if(isNaN(num)) { nu ...
- Java集合类--->入门上篇
最近我又在研究Java语言,这是第五次还是第六次学习Java的集合类,你也许会惊讶为什么这么多次?哈哈,因为之前的我没有记录下来,忘记了,当然最主要还是觉得自己毅力不够,没有坚持.那么,这次我将换一种 ...