Django视图层——中间件概述

Posted aric-zhu

tags:

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

参考文献:

https://docs.djangoproject.com/zh-hans/2.0/topics/http/middleware/

 

 

中间件定义

中间件是一种嵌入django的request和response请求处理的hooks框架。它是一种轻量级的改变Django全局输入或输出的插件。

每个中间件都有一个特定的功能。比如,Django包含一个AuthenticationMiddleware中间件,可以通过sessions将用户和请求关联。

 

 

写自定制的中间件

中间件是可以调用的,它可以调用get_response函数,然后在返回一个中间件。中间件处理一个request请求,然后返回一个response请求,就像view函数一样。如下:

def simple_middleware(get_response):
    # One-time configuration and initialization.

    def middleware(request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

    return middleware

也可以写成类的形式,如下:

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

__init__(get_response)

中间件工厂必须接收get_response参数。也可以初始化一些全局的参数。需要记住以下两点:

  •   Django只使用get_response参数来初始化中间件,所以不能再__init__()方法中定义任何其他参数。
  •   __call__()方法在每次有request请求的时候都会被调用,而__init__()方法只会调用一次,只有当Web服务开始的时候。

 

 

标记中间件未被使用

有时候在启动时决定是否使用中间件是很有用的,在上述情况下,你的中间件的__init__()方法可能会引发MiddlewareNotUsed异常。Django会从中间件进程中移除这个中间件,并且打印一条debug消息的log到django.request的logger中,当DEBUG=True

 

 

激活中间件

将中间件添加到MIDDLEWARE列表来激活。

在MIDDLEWARE中,每一个中间件都由一个字符串代表,到中间件的python路径或者是函数名。下面是django-admin startproject创建的默认值,如下:

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,
]

Django中可以不需要任何的中间件,也就是MIDDLEWARE可以为空。但强烈建议至少使用CommonMiddleware。

MIDDLEWARE中的中间件的顺序是有关系的,因为中间件可以依赖于其他的中间件。比如 , AuthenticationMiddleware在session中保存已验证的用户,它必须在SessionMiddleware中间件运行后再运行。

 

 

中间件顺序与层级

在请求流中,在调用view函数之前,Django会根据在MIDDLEWARE列表中定义的从上往下的顺序来依次应用中间件。

你可以把它想象成一个洋葱:每一个中间件的类都是一层,套在了处在核心的view函数的外围。如果这个请求通过了洋葱的所有层(每一层都会调用get_response来将request传递给下一层),最终到达处于核心处的view函数,然后这个response将会从原路返回每一层(按照原先的逆序的方式)。

如果其中有一层短路了,并且返回了一个不带get_response调用的response,那么接下来的层,包括view都看不到request或者response。这个response请求只会从当前层原路返回。

 

 

其他的中间件钩子

除了基本的request/response中间件,你也可以添加另外三种特殊的方法给基于类的中间件:

 

process_view()

process_view(request, view_func, view_args, view_kwargs)

request 是一个HttpRequest对象。view_func是Django中使用的python函数(是一个实际的函数对象,并不是一个函数名)。view_args是一个位置参数列表,会传递给view函数,view_kwargs是一个字典形式的关键字参数,也会传递给view函数。

view_args和view_kwargs都不包括request参数。

Django在调用view函数之前,process_view()方法会被调用。他会返回None或者HttpResponse对象。如果他返回了None,那么Django会加速这个请求,执行除process_view()以外的中间件,然后执行view函数。如果返回HttpResponse对象,

Django将会不调用view函数,它会将response中间件应用到HttpResponse上,然后返回结果。

注意:在视图运行之前或在process_view()中访问中间件中的request.POST将阻止在中间件之后运行的任何视图能够修改请求的上载处理程序,通常应该避免这种情况的发生。

但这个CsrfViewMiddleware类是个例外,因为它提供了csrf_exempt()以及csrf_protect()装饰器,将允许views明确的控制CSRF应该有效的点。

 

 

 


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

Django - 学习目录

Django之路

在 Django 中间件中访问当前视图类实例

Django 框架

Django框架

Django