中间件

文件夹为middlewareDemo

中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。

Django的中间件的定义:

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.

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',
'app01.my_middlewares.CustomerMiddleware', #这是自定义的
'app01.my_middlewares.CustomerMiddleware2', #自定义的中间件
] from django.middleware.security import SecurityMiddleware #可以点进去查看SecurityMiddleware这个类
from django.contrib.sessions.middleware import SessionMiddleware

每一个中间件都有具体的功能。

django默认7个中间件,其实就是一个类。

django请求周期

接收到了socket,拿到了请求信息,wsgire做了一个封装request的操作(解析数据,解析成一个request的对象)----------------->>>会进入中间件,执行每一个中间件的process_request,它是依次执行的。------>

路由层做分发,分发完了交给视图进行处理,视图要响应一个值,如果是字符串就原路返回了,它返回的时候是依次执行process_response这个方法 走出中间件 ---->

wsgiref封装了数据,(http协议必须按照响应体的响应格式进行发,如果不按照那个格式发浏览器无法解析;wsgiref封装协议,响应首行、响应体、响应体)

把请求体交给浏览器----》拿到响应体浏览器解析为一个页面给用户看。

中间件不管你访问的请求路径是什么,只要请求访问的是这个服务器就必然会通过这个中间件来的时候经过process_respongse,回去的时候经过process_request,属于全局性逻辑处理。

自定义中间件

中间件一共有四个方法:-

process_request

process_view

process_exception

process_response

当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。       这个中间件的类不一定都有procee_request和procee_response,也可能只有一个,没有process_response返回的时候就不经过了。

上述截图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin

需要导入:

from django.utils.deprecation import MiddlewareMixin

process_response是在中间件里边一层层的传,先到第一个个中间件,再到第二个,是依次执行的

视图函数在校验时候,可以把校验写在某个中间件里边去,在这里边写一次,进来的所有请求都可以校验下,不用一个个加装饰器了。

from django.utils.deprecation import MiddlewareMixin
class CustomerMiddleware(MiddlewareMixin): #让它继承下这个类
def process_request(self, request):
print('CustomerMiddleware1 process_request') #默认返回None;然后比如你访问index页面,它就会执行这句话了,走了precess_request class CustomerMiddleware2(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware2 process_request')
'app01.my_middlewares.CustomerMiddleware',  #在settins里边的MIDDLEWARE把它加进去。
'app01.my_middlewares.CustomerMiddleware2', #这两个中间件里边的process_request依次执行; 它是全局的逻辑处理

打印:

CustomerMiddleware1 process_request
CustomerMiddleware2 process_request
index #先走中间件,再进视图函数打印它
[15/Jun/2018 10:01:38] "GET /index/ HTTP/1.1" 200 5

中间件的作用:

大部分视图要做的工作,我们可以放到中间件里边去,比如关于session的验证:好像视图函数必须是在登录之后才能看这个页面,必须在每个视图函数里边加判断或者加装饰器,二三十个视图函数都挂一个装饰器login_request,如果把校验放到中间件里边去,在这里边定义一次,所有的请求都进来之后都会校验它是否登录了

from django.shortcuts import render, HttpResponse

# Create your views here.
def index(request):
print('index') #进来的时候先执行中间件CustomerMiddleware的process_request,再走中间件CustomerMiddleware2的process_request,再打印index;走的时候是反过来走中间件
return HttpResponse("INDEX")
#响应体就是INDEX这个字符串,先执行后边的中间件,先交给CustomerMiddleware2的process_response,执行完自己的逻辑,
  又把response交给了它上一个中间件CustomerMiddleware的process_response,然后执行它的逻辑打印,就这样子传接力棒
def index_new(request): return HttpResponse('index_new')
from django.utils.deprecation import MiddlewareMixin
class CustomerMiddleware(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware1 process_request')
def process_response(self, request,response): #response就是HttpResponse(INDEX)相应体对象
print('CustomeerMiddleware1 process_request')
return response #它必须要有返回值,就像接力棒一层层传给别人;在process_request里边必须要写返回值。 class CustomerMiddleware2(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware2 process_request')
def process_response(self, request,response):
print('CustomeerMiddleware2 process_request')
return response

打印:

CustomerMiddleware1 process_request
CustomerMiddleware2 process_request
index
CustomeerMiddleware2 process_request
CustomeerMiddleware1 process_request
[15/Jun/2018 10:11:12] "GET /index/ HTTP/1.1" 200 5
#相应体就是INDEX这个字符串,先执行后边的中间件,先交给CustomerMiddleware2的process_response,执行完自己的逻辑,
又把response交给了它上一个中间件的process_response,然后执行它的逻辑打印,就这样子传接力棒

如果非要在process_request加个返回值,

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class CustomerMiddleware(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware1 process_request')
return HttpResponse('forbidden..') def process_response(self, request,response): #response就是HttpResponse(INDEX)相应体对象
print('CustomeerMiddleware1 process_request')
return response #它必须要有返回值,就像接力棒一层层传给别人 class CustomerMiddleware2(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware2 process_request')
def process_response(self, request,response):
print('CustomeerMiddleware2 process_request')
return response
CustomerMiddleware1 process_request
CustomeerMiddleware1 process_request
[15/Jun/2018 10:29:42] "GET /index/ HTTP/1.1" 200 11 #访问http://127.0.0.1:8000/index/打印的是forbidden..,

没有执行中间件2的内容,也没有执行视图。

url请求中间件1的process_request的时候,一旦加了返回值,直接把相应体交给自己的process_response,交给浏览器。一下子给拦截了。应用场景:拦截,你的ip频率太高;session进行校验的时候没有登录也给你拦截下来。

process_view(这个视图方法)

加了process_view之后打印执行的顺序:

[15/Jun/2018 10:40:45] "GET /index/ HTTP/1.1" 200 5
CustomerMiddleware1 process_request
CustomerMiddleware2 process_request
CustomerMiddleware1:process_view
CustomerMiddleware2:process_view
index
CustomeerMiddleware2 process_request
CustomeerMiddleware1 process_request
#Author:Kris

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class CustomerMiddleware(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware1 process_request')
#return HttpResponse('forbidden..')
def process_view(self, request, callback, callback_args, callback_kwargs):
print("CustomerMiddleware1:process_view") def process_response(self, request,response): #response就是HttpResponse(INDEX)相应体对象
print('CustomeerMiddleware1 process_response')
return response #它必须要有返回值,就像接力棒一层层传给别人 class CustomerMiddleware2(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware2 process_request')
def process_response(self, request,response):
print('CustomeerMiddleware2 process_response')
return response def process_view(self, request, callback, callback_args, callback_kwargs):
#print("===>",callback) #===> <function index at 0x0000000003DE11E0> 视图函数
#在进入到2的视图函数的时候,把响应体体返回了 123,那么视图函数就不执行了,接着往下执行process_response
print("===>",callback(callback_args)) #不走视图函数了我提前拿到它的响应结果 print("CustomerMiddleware2:process_view")
ret = callback(callback_args) ###可以进行拦截。
return ret #把它的结果返回了就可以拿到视图函数里边的index了
#return HttpResponse('123')
上边的执行结果
CustomerMiddleware1 process_request
CustomerMiddleware2 process_request
CustomerMiddleware1:process_view
index
===> <HttpResponse status_code=200, "text/html; charset=utf-8">
CustomerMiddleware2:process_view
index
CustomeerMiddleware2 process_response
CustomeerMiddleware1 process_response
def process_view(self, request, callback, callback_args, callback_kwargs):

        #在进入到2的视图函数的时候,把响应体返回了 123,那么视图函数就不执行了,接着往下执行process_responseprint("CustomerMiddleware2:process_view")
return HttpResponse('') #没有走index,在这里返回了123 CustomerMiddleware1 process_request
CustomerMiddleware2 process_request
CustomerMiddleware1:process_view CustomerMiddleware2:process_view
CustomeerMiddleware2 process_response
CustomeerMiddleware1 process_response

process_exception(这个方法)

流程图如下:

当views出现错误时:

views.py
def index(request):
print('index')
kris
return HttpResponse("INDEX")
CustomerMiddleware1 process_request
CustomerMiddleware2 process_request
CustomerMiddleware1:process_view
CustomerMiddleware2:process_view
index #打印完视图就报错了,报错没有拿到响应体HttpResponse(index),直接走下面的process_exception
CustomeerMiddleware2 process_exception
CustomeerMiddleware1 process_exception
Internal Server Error: /index/ 出错

CustomeerMiddleware2 process_response
  CustomeerMiddleware1 process_response

#Author:Kris

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class CustomerMiddleware(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware1 process_request')
#return HttpResponse('forbidden..')
def process_view(self, request, callback, callback_args, callback_kwargs):
print("CustomerMiddleware1:process_view") def process_response(self, request,response): #response就是HttpResponse(INDEX)相应体对象
print('CustomeerMiddleware1 process_request')
return response #它必须要有返回值,就像接力棒一层层传给别人
def process_exception(self, request, exception):
print('CustomeerMiddleware1 process_exception') class CustomerMiddleware2(MiddlewareMixin):
def process_request(self, request):
print('CustomerMiddleware2 process_request')
def process_response(self, request,response):
print('CustomeerMiddleware2 process_request')
return response def process_view(self, request, callback, callback_args, callback_kwargs):
#print("===>",callback) #===> <function index at 0x0000000003DE11E0> 视图函数
#在进入到2的视图函数的时候,把相应体返回了 123,那么视图函数就不执行了,接着往下执行process_response
#print("===>",callback(callback_args)) print("CustomerMiddleware2:process_view")
# ret = callback(callback_args)
# return ret #把它的结果返回了就可以拿到index了
#return HttpResponse('123')
def process_exception(self, request, exception):
print('CustomeerMiddleware2 process_exception')
return HttpResponse(exception) #一旦有一个return了,后边1的process_exception就不执行了;把它的错误信息给返回了呗
CustomerMiddleware1 process_request
CustomerMiddleware2 process_request
CustomerMiddleware1:process_view
CustomerMiddleware2:process_view
index
CustomeerMiddleware2 process_exception #直接检测完,把它的错误捕捉到交给响应体返回了,就不执行1的process_exception了
CustomeerMiddleware2 process_response
CustomeerMiddleware1 process_response
[15/Jun/2018 11:34:36] "GET /index/ HTTP/1.1" 200 26

如果把写到1里边,2不要,return HttpResponse(exception)

CustomerMiddleware1 process_request
CustomerMiddleware2 process_request
CustomerMiddleware1:process_view
CustomerMiddleware2:process_view
index
CustomeerMiddleware2 process_exception
CustomeerMiddleware1 process_exception
CustomeerMiddleware2 process_response
CustomeerMiddleware1 process_response
[15/Jun/2018 11:37:28] "GET /index/ HTTP/1.1" 200 26

综上:

会process_request、process_response这两个就足够了,要知道它的实现流程,process_request没有返回值,如果有返回值就原路返回了,下边的中间件、视图函数都不执行了;process_response必须要有返回值,如果它没有返回值就没人传这个接力棒response了,这个接力棒是--> 如果视图函数是正确的就是它的响应体,如果发生错误了就是exception的响应体。

如果我在process_response没有把它的 return response返回,自己定义了return HttpResponse("Hello kris"),相当于在接力的过程中我把接力棒给换了。

应用URL访问过滤 在auth_Demo文件夹里边

如果用户访问的是login视图(放过)

如果访问其他视图,需要检测是不是有session认证,已经有了放行,没有返回login,这样就省得在多个视图函数上写装饰器了!

my_middlewares.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect
from authDemo import settings class AuthMiddleware(MiddlewareMixin): #认证
def process_request(self, request):
white_list = settings.WHITE_LIST #先拿到那个白名单
if request.path in white_list:
return None #相当于通过校验
if not request.user.is_authenticated:
return redirect("/login/")

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',
'app01.my_middlewares.AuthMiddleware', #把它加上去 ] LOGIN_URL = "/login/" #跳转到哪里由我自己决定; WHITE_LIST = ["/login/","/reg/","logout/"] #设置下白名单

11.Django|中间件的更多相关文章

  1. django CBV装饰器 自定义django中间件 csrf跨站请求伪造 auth认证模块

    CBV加装饰器 第一种 @method_decorator(装饰器) 加在get上 第二种 @method_decorator(login_auth,name='get') 加在类上 第三种 @met ...

  2. Django中间件-跨站请求伪造-django请求生命周期-Auth模块-seettings实现可插拔配置(设计思想)

    Django中间件 一.什么是中间件 django中间件就是类似于django的保安;请求来的时候需要先经过中间件,才能到达django后端(url,views,models,templates), ...

  3. django中间件 csrf auth认证

    django中间件 能做全局访问频率限制,身份校验,黑名单,白名单 用法: 新建一个文件夹,文件夹新建一个py文件,文件中写如下代码 注意点:你写的类必须继续MiddlewareMixin from ...

  4. python之路54 forms组件 渲染 展示 参数补充 modelform组件 django中间件

    forms组件渲染标签 <p>forms组件渲染标签的方式1(封装程度高 扩展性差 主要用于本地测试):</p> {# {{ form_obj.as_p }}#} {# {{ ...

  5. Django数据操作F和Q、model多对多操作、Django中间件、信号、读数据库里的数据实现分页

    models.tb.objects.all().using('default'),根据using来指定在哪个库里查询,default是settings中配置的数据库的连接名称. 外话:django中引 ...

  6. django 中间件

    django处理一个Request的过程是首先通过django 中间件,然后再通过默认的URL方式进行的.所以说我们要做的就是在django 中间件这个地方把所有Request拦截住,用我们自己的方式 ...

  7. day20 FORM补充(随时更新),F/Q操作,model之多对多,django中间件,缓存,信号

    python-day20 1.FROM生成select标签的数据应该来源于数据库. 2.model 操作 F/Q  (组合查询) 3.model 多对多操作. 4.中间件 :在请求到达url前先会经过 ...

  8. Django学习之七:Django 中间件

    目录 Django 中间件 自定义中间件 - - - 大体两种方式 将中间件移除 实例 中间件加载源码阅读 总结 Django 中间件 Tips: 更新日志: 2019.01.31 更新django中 ...

  9. Django中间件的使用

    Django中间件的使用 中间件(middleware) 中间件应用于request与服务端之间和服务端与response之间,客户端发起请求到服务端接收可以通过中间件,服务端返回响应与客户端接收响应 ...

随机推荐

  1. pyinstaller 打包不成功,提示inporterror 缺少xlrd、xlwt

    问题:pyinstaller 打包不成功,提示inporterror 缺少xlrd.xlwt 解决:将 pypiwin 230 改为 219

  2. aar jar包打包

    使用Android Studio Module的方式编译出aar和jar包: aar包:打aar包时,gradle compile依赖编译进来的包不会被打到aar包中,所以接入aar的应用仍然需要添加 ...

  3. 使用block的时候,导致的内存泄漏

    明确,只要在block里边用到我们自己的东西,成员变量,self之类的,我们都需要将其拿出来,把它做成弱指针以便之后进行释放. 在ZPShareViewController这个控制器中,由如下代码: ...

  4. activity 解析

    acitvity的四种状态: running.paused.stopped.killed 生命周期: onCreate()用来加载资源布局 onStart()启动activity,用户已经可以看到界面 ...

  5. ubuntu下安装intel realsense驱动

    在安装之前一定要确保系统是ubuntu 14.04.3 64位! 由于一开始安装的是32位系统,导致在升级内核版本到4.4时各种问题,最终靠重装系统解决. 因为intel给出的测试代码均是在64位14 ...

  6. k64 datasheet学习笔记3---Chip Configuration之Clock modules

    1.前言 本文主要讲述chip configure之clock配置相关的内容,主要包含如下三个部分: MCG configuration:Multipurpose clock generator OS ...

  7. TERMIOS详解【转】

    转自:https://blog.csdn.net/guo_wangwei/article/details/1102931# TERMIOS NAME termios, tcgetattr, tcset ...

  8. oracle 远程导入导出(本地win)

    导出 exp hongtastock_account/hongtastock_account@192.168.1.22/orcl file=D:\hongta\hongtastock_account. ...

  9. Tomcat启动项目时内存溢出问题如何解决

    在Eclipse中,内存溢出(报不能创建JAVA虚拟机错时,也可能是这里配错了.) 1.双击Tomcat,点击Open launch configuration,Arguments, 2.在VM ar ...

  10. 红黑树与AVL树

    概述:本文从排序二叉树作为引子,讲解了红黑树,最后把红黑树和AVL树做了一个比较全面的对比. 1 排序二叉树 排序二叉树是一种特殊结构的二叉树,可以非常方便地对树中所有节点进行排序和检索. 排序二叉树 ...