day62 中间件
一.中间件的介绍
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级, 并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用, 用不好会影响到性能
1. Django 的请求生命周期
2.Django默认自带的一些中间件
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', ]
3.执行中间件的过程
二. 自定义中间件
1.在项目中创建一个包
在项目中创建一个包,随便起名字,一般都放在一个叫做utils的包里面, 表示一个公用的组件,创建一个py文件,随便起名字, 例如叫做:middlewares.py,内容如下
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): #自定义中间件,不是必须要有下面这两个方法,有request方法说明请求来了要处理,有response方法说明响应出去时需要处理,不是非要写这两个方法,如果你没写process_response方法,那么会一层一层的往上找,哪个中间件有process_response方法就将返回对象给哪个中间件 def process_request(self, request): print("MD1里面的 process_request") def process_response(self, request, response): print("MD1里面的 process_response") return response
2.在 settings.py 文件中进行注册
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', 'utils.middlewares.MD1', # 自定义中间件MD1,这个写的是你项目路径下的一个路径, 例如,如果你放在项目下,文件夹名成为utils, 那么这里应该写utils.middlewares.MD1 'utils.middlewares.MD2' # 自定义中间件MD2 ]
三.常用方法
1. process_request
process_request有一个参数,就是request,这个request和 视图函数中的request是一样的。 它的返回值可以是None也可以是HttpResponse对象。返回值是None的话, 按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象, Django将不执行视图函数,而将相应对象返回给浏览器。
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") pass
①在注册时 先注册 MD1 再注册 MD2,打印结果为:
MD1里面的 process_request MD2里面的 process_request app01 中的 index视图
②在注册时 先注册MD2 再注册 MD1,打印结果为:
MD2里面的 process_request MD1里面的 process_request app01 中的 index视图
注: 多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的, 也就是说第一个中间件的process_request方法首先执行,而它的process_response 方法最后执行,最后一个中间件的process_request方法最后一个执行, 它的process_response方法是最先执行。
2. process_response
它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象, response是视图函数返回的HttpResponse对象。该方法的返回值也必须是HttpResponse对象。
①示例1:
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") #不必须写return值 def process_response(self, request, response):#request和response两个参数必须有,名字随便取 print("MD1里面的 process_response") #print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容的方法 return response #必须有返回值,写return response ,这个response就像一个接力棒一样 #return HttpResponse('瞎搞') ,如果你写了这个,那么你视图返回过来的内容就被它给替代了 class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") pass def process_response(self, request, response): #request和response两个参数必须要有,名字随便取 print("MD2里面的 process_response") return response #必须返回response,不然你上层的中间件就没有拿到httpresponse对象,就会报错
结果:
MD2里面的 process_request MD1里面的 process_request app01 中的 index视图 MD1里面的 process_response MD2里面的 process_response
看结果可知: process_response方法是在视图函数之后执行的,并且顺序是MD1比MD2先执行。 (此时settings.py中 MD2比MD1先注册) 多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的, 也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行, 最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行。
②示例2:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class Md1(MiddlewareMixin): def process_request(self,request): print("Md1请求") return HttpResponse("Md2中断")
#process_request方法里面不写返回值,默认也是返回None,如果你自己写了return None, 也是一样的效果,不会中断你的请求,但是如果你return 的一个httpresponse对象, 那么就会在这个方法中断你的请求,直接返回给用户,这就成了非正常的流程了 #并且,如果你在这里return了httpresponse对象,那么会从你这个中间件类中的 process_response方法开始执行返回操作,所以这个类里面只要有process_response方法, 肯定会执行 def process_response(self,request,response): print("Md1返回") return response class Md2(MiddlewareMixin): def process_request(self,request): print("Md2请求") def process_response(self,request,response): print("Md2返回") return response
结果为:
Md1请求 Md1返回
流程图如下:
实例: 访问白名单设置
class M1(MiddlewareMixin): def process_request(self,request): #设置路径白名单,只要访问的是login登陆路径,就不做这个cookie认证 if request.path not in [reverse('login'),]: print('我是M1中间件') #客户端IP地址 # return HttpResponse('sorry,没有通过我的M1中间件') is_login = request.COOKIES.get('is_login', False) if is_login: pass else: # return render(request,'login.html') return redirect(reverse('login')) else: return None #别忘了return None def process_response(self,request,response): print('M1响应部分') # print(response.__dict__['_container'][0].decode('utf-8')) return response # return HttpResponse('瞎搞')
3. process_view
process_view(self, request, view_func, view_args, view_kwargs) 该方法有四个参数 request是HttpRequest对象。 view_func是Django即将使用的视图函数。 ( 它是实际的函数对象,而不是函数的名称作为字符串。) view_args是将传递给视图的位置参数的列表. view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。 Django会在调用视图函数之前,路由匹配之后(process_request方法之后)调用process_view方法。
① 流程图
② 示例:(访问index视图函数)
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") def process_response(self, request, response): print("MD1里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD1 中的process_view") print(view_func, view_func.__name__) #就是url映射到的那个视图函数, 也就是说每个中间件的这个process_view已经提前拿到了要执行的那个视图函数 #ret = view_func(request) #提前执行视图函数,不用到了上图的试图函数的位置再执行, 如果你视图函数有参数的话,可以这么写 view_func(request,view_args,view_kwargs) #return ret #直接就在MD1中间件这里这个类的process_response给返回了, 就不会去找到视图函数里面的这个函数去执行了。 class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") pass def process_response(self, request, response): print("MD2里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD2 中的process_view") print(view_func, view_func.__name__)
结果:
MD1里面的 process_request MD2里面的 process_request -------------------------------------------------------------------------------- MD1 中的process_view <function index at 0x000001DE68317488> index -------------------------------------------------------------------------------- MD2 中的process_view <function index at 0x000001DE68317488> index app01 中的 index视图 MD2里面的 process_response MD1里面的 process_response
③写了返回对象的情况
返回值是HttpResponse: 当前中间件之后的中间的process_view方法和视图函数都不执行,直接执行最后一个中间件的process_reponse方法.
4.process_exception
process_exception(self, request, exception) 该方法两个参数: 一个HttpRequest对象 一个exception是视图函数异常产生的Exception对象。 这个方法只有在视图函数中出现异常了才执行, 它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象, Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。 如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。 它的执行顺序也是按照中间件注册顺序的倒序执行。
①示例1:
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") def process_response(self, request, response): print("MD1里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD1 中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("MD1 中的process_exception") class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") pass def process_response(self, request, response): print("MD2里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD2 中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("MD2 中的process_exception")
在视图函数中抛出一个异常
def index(request): print("app01 中的 index视图") raise ValueError("呵呵") return HttpResponse("O98K")
流程图:
②示例2:在process_exception中返回一个响应对象
class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") def process_response(self, request, response): print("MD2里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD2 中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("MD2 中的process_exception") return HttpResponse(str(exception)) # 返回一个响应对象
结果:
MD1里面的 process_request MD2里面的 process_request -------------------------------------------------------------------------------- MD1 中的process_view <function index at 0x0000022C09727488> index -------------------------------------------------------------------------------- MD2 中的process_view <function index at 0x0000022C09727488> index app01 中的 index视图 呵呵 MD2 中的process_exception MD2里面的 process_response MD1里面的 process_response
流程图:
返回None: 正常流程. 返回HttpResponse对象: 后面的中间件的process_view方法不执行,直接执行最后一个中间件的process_response方法.
process_template_response(用的比较少)
process_template_response(self, request, response)
它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)。
process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。
class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") def process_response(self, request, response): print("MD1里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD1 中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("MD1 中的process_exception") return HttpResponse(str(exception)) def process_template_response(self, request, response): print("MD1 中的process_template_response") return response class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") def process_response(self, request, response): print("MD2里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD2 中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("MD2 中的process_exception") def process_template_response(self, request, response): print("MD2 中的process_template_response") return response
views.py中:
def index(request): print("app01 中的 index视图") def render(): print("in index/render") return HttpResponse("O98K") rep = HttpResponse("OK") rep.render = render return rep
访问index视图,终端输出的结果:
MD2里面的 process_request MD1里面的 process_request -------------------------------------------------------------------------------- MD2 中的process_view <function index at 0x000001C111B97488> index -------------------------------------------------------------------------------- MD1 中的process_view <function index at 0x000001C111B97488> index app01 中的 index视图 MD1 中的process_template_response MD2 中的process_template_response in index/render MD1里面的 process_response MD2里面的 process_response
从结果看出:
视图函数执行完之后,立即执行了中间件的process_template_response方法,顺序是倒序,先执行MD1的,在执行MD2的,接着执行了视图函数返回的HttpResponse对象的render方法,返回了一个新的HttpResponse对象,接着执行中间件的process_response方法。
补充: 登录时浏览器自动加 "/"
①在输入时
②浏览器自动加 '/'
③在一些情况下不需要加时,
在settings.py文件中进行设置
day62 中间件的更多相关文章
- ASP.NET Core 中的那些认证中间件及一些重要知识点
前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...
- ASP.NET Core应用的错误处理[3]:ExceptionHandlerMiddleware中间件如何呈现“定制化错误页面”
DeveloperExceptionPageMiddleware中间件利用呈现出来的错误页面实现抛出异常和当前请求的详细信息以辅助开发人员更好地进行纠错诊断工作,而ExceptionHandlerMi ...
- ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”
在<ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式>中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将 ...
- ASP.NET Core 中间件之压缩、缓存
前言 今天给大家介绍一下在 ASP.NET Core 日常开发中用的比较多的两个中间件,它们都是出自于微软的 ASP.NET 团队,他们分别是 Microsoft.AspNetCore.Respons ...
- .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法
.NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...
- .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类
.NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类 0x00 为什么要引入扩展方法 有的中间件功能比较简单,有的则比较复杂,并且依赖其它组件.除 ...
- .NET Core中间件的注册和管道的构建(1)---- 注册和构建原理
.NET Core中间件的注册和管道的构建(1)---- 注册和构建原理 0x00 问题的产生 管道是.NET Core中非常关键的一个概念,很多重要的组件都以中间件的形式存在,包括权限管理.会话管理 ...
- 从中间件的历史来看移动App开发的未来
在移动开发领域我们发现一个很奇怪的现象:普通菜鸟新手经过3个月的培训就可以拿到 8K 甚至上万的工作:在北京稍微有点工作经验的 iOS 开发,就要求 2 万一个月的工资.不知道大家是否想过:移动应用开 ...
- ASP.NET Core的路由[4]:来认识一下实现路由的RouterMiddleware中间件
虽然ASP.NET Core应用的路由是通过RouterMiddleware这个中间件来完成的,但是具体的路由解析功能都落在指定的Router对象上,不过我们依然有必要以代码实现的角度来介绍一下这个中 ...
随机推荐
- Redis 分布式锁及缓存注释的使用方法
使用工具:Apache an 测压命令: ab -n 100 -c 100 http://www.baidu.com -n代表模拟100个请求,-c代表模拟100个并发,相当于100个人同时访问 ab ...
- python入门之小栗子
1 点球小游戏: from random import choice score=[0,0]direction=['left','center','right'] def kick(): print ...
- 【转】git - 简易指南
原文链接:http://www.bootcss.com/p/git-guide/ 作者:罗杰·杜德勒 感谢:@tfnico, @fhd and Namics 其他语言 english, deutsch ...
- 总结vue中父向子,子向父以及兄弟之间通信的几种方式
子向父方式1:通过props,如例子中子组件test1.vue向父组件App.vue传值 App.vue代码 <template> <div id="app"&g ...
- 芯片烧录器编程AT24C02
网上买了两款芯片烧录器,因为项目用的到.芯片以后的类型可能是IIC 接口的.就选则了一个IIC接口的AT24C02EEPROM.进行尝试.手头上没有这款芯片. 就想起自己单片机上有这款芯片.然后就开始 ...
- pandas 常用函数
- JAVAEE期末项目------文章发布系统
项目文档和代码的GitHub地址:https://github.com/xiangbaobaojojo/- 1.项目介绍 (计科四班 蔡春燕 20150141401)和我 陈香宇(计科四班 201 ...
- [转载] java多线程总结(三)
转载自: http://www.cnblogs.com/lwbqqyumidi/p/3821389.html 作者:Windstep 本文主要接着前面多线程的两篇文章总结Java多线程中的线程安全问题 ...
- vue-router 学习
Vue.js的一大特色就是构建单页面应用十分方便,既然要方便构建单页面应用那么自然少不了路由,vue-router就是vue官方提供的一个路由框架.总体来说,vue-router设计得简单好用,下面就 ...
- python super超类方法
super() 函数是用于调用父类(超类)的一个方法. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO).重复调用( ...