django基础 -- 9.中间件
一.中间件的介绍
中间件顾名思义,是介于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_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
③写了返回对象的情况
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
流程图:
5.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("-" * )
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("-" * )
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
访问视图函数,输出的结果是
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文件中进行设置
django基础 -- 9.中间件的更多相关文章
- Django基础之中间件
1. 引入 在之前学习的过程中,已经学会了给视图函数加装饰器来判断用户是否登录,把没有登录的用户请求跳转到登录页面. 我们通过给几个特定视图函数加装饰器实现了这个需求. 但是以后添加的视图函数可能也需 ...
- Django基础之中间件的执行流程
当请求到达中间件以后,先按照正序执行每个注册中间件的process_request方法,process_request方法返回的值是None,就依次执行. 如果返回的值是HttpResponse对象, ...
- {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证
Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...
- day 63 Django基础九之中间件
Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学 ...
- Django基础七之CBV装饰器和中间件
Django基础七之CBV装饰器和中间件 目录 Django基础七之CBV装饰器和中间件 1. CBV加装饰器 2. Django中间件 2.1 Django中间件介绍 2.2 自定义中间件 2.2. ...
- Python学习(二十六)—— Django基础一
转载自:http://www.cnblogs.com/liwenzhou/p/8258992.html 一.Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的 ...
- Django基础和基本使用
Django基础 Django是Python下的一款著名的Web框架 框架 任何语言进入到高级部分时,会有认证.session.http.连接数据库等等功能操作,没有框架时需要自己实现 框架 是整个或 ...
- {Django基础八之cookie和session}一 会话跟踪 二 cookie 三 django中操作cookie 四 session 五 django中操作session
Django基础八之cookie和session 本节目录 一 会话跟踪 二 cookie 三 django中操作cookie 四 session 五 django中操作session 六 xxx 七 ...
- 老师的blog整理 .网络编程部分 .网络编程部分 前端部分 django基础部分
老师的blog整理 python基础部分: 宝哥blog: https://www.cnblogs.com/guobaoyuan/ 开哥blog: https://home.cnblogs.com/u ...
随机推荐
- 阿里云云盾服务证书免费CA证书申请与配置 (原)
申请入口(首页导航产品->安全->CA证书服务->立即购买) 免费版选择步骤一步一步来 1.品牌选 Symantec 2.保护类型选择 一个域名(免费版只能一个好像) 3.证书类型选 ...
- 去掉idea中竖线
1.现象如下: 2.解决办法. 3.解决后如下:
- SEO经验-如何做到新站上线半个月谷歌收录3万
一个网站在做搜索引擎优化的时候,首先考虑的肯定是百度,这个是毋庸置疑的,毕竟百度占领者差不多七成的搜索市场份额. 第二考虑的是360搜索,这个也是毋庸置疑的,因为360搜索占领者差不多两成的搜索市场份 ...
- STL之Set和multiset容器
1.Set和multiset容器 1)set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. 2)set采用红黑树变体的数据 ...
- 阿里云Centos7 yum安装MySQL5.6
安装mysql5姿势是要先安装带有可用的mysql5系列社区版资源的rpm包 [root@iZ28gvqe4biZ ~]# rpm -Uvh http://dev.mysql.com/get/mysq ...
- 05 enumerate index使用
# enumerate 自动生成一列, 默认0开始,每次自增+1li = ["电脑","鼠标垫","U盘","游艇"]f ...
- MQTT 发布者订阅者
添加依赖: <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclip ...
- Applegate 方法使用
1. - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotif ...
- 【Hadoop学习之二】Hadoop伪分布式安装
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 伪分布式就 ...
- 【转】基于 Kylin 的推荐系统效果评价系统
OLAP(联机分析处理)是数据仓库的主要应用之一,通过设计维度.度量,我们可以构建星型模型或雪花模型,生成数据多维立方体Cube,基于Cube可以做钻取.切片.旋转等多维分析操作.早在十年前,SQL ...