Django 中间件 Middleware

Posted 亦非我所愿丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django 中间件 Middleware相关的知识,希望对你有一定的参考价值。

文章目录

一、中间件

Middleware是Django请求/响应处理的插件框架。它是一个轻巧的低级"插件"系统,用于全局改变Django的输入或输出。

每个中间件组件负责执行某些特定功能。例如,Django包含一个中间件组件 AuthenticationMiddleware,它将用户与使用会话的请求相关联。

该文档介绍了中间件的工作原理,如何激活中间件以及如何编写自己的中间件。Django附带了一些你可以直接使用的内置中间件。它们记录在内置中间件参考中


二、激活中间件

要激活中间件,请将其添加到MIDDLEWARE Django设置中的列表中
如下,我激活了三个中间件 Middleware.test.m1,Middleware.test.m2,Middleware.test.m3

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',
    'Middleware.test.m1',
    'Middleware.test.m2',
    'Middleware.test.m3',
]

三、中间件请求和响应

在请求阶段,调用views之前,django按照MIDDLEWARE_CLASSES中定义的顺序从上到下调用中间件。

在Django中间件中,总共有分为从上到下hooks和从下到上hooks

从上到下hooks:

  • process_request()
  • process_view()

从下到上hooks:

  • process_exception()
  • process_template_response()
  • process_response()

四、中间件处理流程说明(如下述的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',
    'Middleware.test.m1',
    'Middleware.test.m2',
    'Middleware.test.m3',
]

一个中间件最少有一个process_request hooks和一个process_response hooks,前者是用来处理请求的,后者是用来处理响应的

那除了必须的两个hooks以外,还有其他三个hooks,分别是 process_view, process_exception, process_template_response

process_view 主要是用来执行middleware中具体的处理函数,如中间件请求中所说,是从上到下的hooks,表示process_view在views视图函数之前执行

process_exception 一般情况下不会执行,只有在views视图函数中出现exception异常时,才会执行;如中间件请求中所说,是从下到上的hooks,表示processs_exception在views视图函数之后执行,也就是views视图函数出错之后,才会执行

processs_template_response 一般情况下也不会执行,也就是说,只有views中的函数返回对象中具有render方法,它才会执行


五、中间件处理顺序(如下述的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',
    'Middleware.test.m1',
    'Middleware.test.m2',
    'Middleware.test.m3',
]

1、process_request 阶段
当一个用户发起请求后,该请求会经过上述的所有中间件,并且自上而下执行;先执行所有中间件的 process_request方法,该方法如果返回HttpResponse,则执行从当前的中间件向上执行 process_responsse,如果返回None,则接着向下执行 process_request

2、process_view 阶段
当该用户的请求执行完所有中间件 process_request 方法后,如果返回都为None,那么接下来会执行所有中间件的 process_view 方法,如果其中一个 process_view 返回HttpResponse,则会跳过接下来所有中间件的 process_view,直接会从最下面的process_response自下而上执行,如果process_view返回None,则会继续向下执行

3、views 阶段
当该用户的请求执行完所有的process_request和process_view阶段,并且没有返回HttpResponse;换句话说,返回的都是None,那么这个时候就会到达views视图函数

在这里,可能会有三种可能性
(1) views中的函数返回对象中具有render方法
(2) views中的函数产生异常
(3) views中的函数返回对象中具有render方法,并且views中的函数产生异常

当出现第一种情况的时候,函数就会开始执行所有中间件的 process_template_response 方法,并且自下而上在每个中间件中挨个执行(当有定义 process_template_response 方法的时候)
当出现第二种情况的时候,函数就会开始执行所有中间件的 process_exception 方法,并且自下而上在每个中间件中挨个执行(当有定义 process_exception 方法的时候)
当出现第三种情况的时候,函数就会自下而上同时执行所有中间件中定义的 process_exception 和 process_template_response 方法(在这个时候会优先执行所有中间件中的process_template_response 方法,再执行所有中间件中的process_exception方法)

4、process_response 阶段
当 process_request, process_view,views,process_template_response,process_exception 方法都执行完成后,开始自下而上从中间件中执行 process_response 方法,直到最上层中间件的 process_response 方法执行完毕,接着返回给用户


六、Django 自定义中间件

1、在settings中定义三个中间件


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',
    'Middleware.test.m1',
    'Middleware.test.m2',
    'Middleware.test.m3',
]

2、创建中间件路径

在项目跟路径下面创建中间件路径
./Middleware/test.py


3、定义中间件

from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse

class m1(MiddlewareMixin):
    def process_request(self, request):
        print('m1 request')

    def process_view(self, request, func_view, func_args, func_kwargs):
        print('m1 view')

    def process_response(self, request, response):
        print('m1 response')
        return response

    def process_exception(self, request, exception):
        print('m1 exception')

    def process_template_response(self, request, response):
        print('m1 template response')
        return response


class m2(MiddlewareMixin):
    def process_request(self, request):
        print('m2 request')

    def process_view(self, request, func_view, func_args, func_kwargs):
        print('m2 view')

    def process_response(self, request, response):
        print('m2 response')
        return response

    def process_exception(self, request, exception):
        print('m2 exception')

    def process_template_response(self, request, response):
        print('m2 template response')
        return response


class m3(MiddlewareMixin):
    def process_request(self, request):
        print('m3 request')

    def process_view(self, request, func_view, func_args, func_kwargs):
        print('m3 view')

    def process_response(self, request, response):
        print('m3 response')
        return response

    def process_exception(self, request, exception):
        print('m3 exception')

    def process_template_response(self, request, response):
        print('m3 template response')
        return response

4、定义视图函数

class Foo:
    def render(self):
        int('v')
        return HttpResponse('OK')

def middleware(request):
    #return render(request, 'login.html')
    #return HttpResponse('middleware')
    return Foo()

七、一个请求经过中间件的请求周期

由于views视图函数中有个报错需要触发中间件中定义的 process_exception 方法,所以便于展示执行顺序,我去除了具体的报错内容

m1 request
m2 request
m3 request
m1 view
m2 view
m3 view
m3 template response
m2 template response
m1 template response
m3 exception
m2 exception
m1 exception
m3 response
m2 response
m1 response


八、结论

大家可根据自己需求自行编写中间件,并且测试中间件中每个方法的执行顺序,总共有5个方法,分别为
process_request
process_view
process_template_response
process_exception
process_response

另外:
Django 官方不建议在中间件层处理 request.POST 数据,csrf中间件是个例外,因为要全局安全处理用户token

以上是关于Django 中间件 Middleware的主要内容,如果未能解决你的问题,请参考以下文章

Django 中间件 Middleware

django之(中间件)middleware

django之中间件middleware

利用django中间件django.middleware.csrf.CsrfViewMiddleware防止csrf攻击

中间件-Middleware

Django 中间件