zoukankan      html  css  js  c++  java
  • [TimLinux] Django 中间件

    1. 定义

    中间件是一个钩子框架,深入到django的请求/响应处理过程中。这是一个轻量、底层插件系统,目的是全局修改django的输入或输出。每一个中间件组件都是用来处理特定的功能。例如django中间件组件:AuthenticationMiddleware用来关联请求用户,采用的方式是使用session。

    2. 原理

    中间件工厂是一个可调用对象,接收get_response作为参数,并返回一个中间件,返回的中间件也是一个可调用对象,接收一个request,并返回一个response,向一个view函数,中间件工厂其实很像装饰器。具体实现方式有:函数方式(像使用函数实现的装饰器)、类方式(像使用类实现的装饰器)。示例代码如下:

    def simple_middleware(get_response):
        # 这里添加代码:一次性配置和初始化
        def middleware(request):
            # 这里添加代码:在view、下一个中间件执行之前执行的代码
            response = get_response(request)
            # 这里添加代码:view调用之后,为每一个请求/响应代码
            return response
        return middleware
    
    
    class SimpleMiddleware(object):
        def __init__(self, get_response):
            self.get_response = get_response
            # 这里添加代码:一次性配置和初始化
    
        def __call__(self, request):
            # 这里添加代码:在view、下一个中间件执行之前执行的代码
            response = get_response(request)
            # 这里添加代码:view调用之后,为每一个请求/响应代码
            return response

     get_response可调用对象是由django提供的:可能是一个真实的view函数(如果是最后列出的中间件)、或者中间件链中的下一个中间件。当前中间件不需要知道或者关心get_response是什么,只要明白它将呈现下一步内容。

    3. 存放路径

    中间件是存放在一个Python文件中,可能放在任意Python搜索文件方式的路径中,只要能够在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.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    4. 解析步骤

    根据请求阶段,在调用view函数之前,django按照定义在MIDDLEWARE中的顺序,从上往下应用中间件。请求是从上往下一层一层往下传递get_response,直到核心(view),响应则是返回来的顺序(由核心开始)。如果某一层决定短路并返回一个响应,而没有调用它的get_repsonse,那么在内部的层(包括view函数)都将被看不到请求和响应。

    顺序:__call__: 前部分 --> self.get_response(request) --> 后部分

    self.get_response(request)内部顺序:process_view() -> view函数

    多个中间件:同名函数先执行,比如:(中间件A的__call__前部分 --> 中间件B的前部分)前部分 --> (中间件A的process_view --> 中间件B的process_view)self.get_response(request) --> (中间件B的__call__后部分 --> 中间件A的后部分)后部分

     

    5. 中间件钩子

    出了前面描述的基本请求响应中间件模式,你可以添加另外三个特殊的方法(基于类的中间件),另外还有两个函数是旧式风格(MIDDLEWARE_CLASSES):

    5.1. process_view():

    process_view(request, view_func, view_args, view_kwargs)

    • request:请求对象,view_func:函数对象,view_args: view的位置参数,view_kwargs: view的关键字参数,view_args和view_kwargs都不包含request对象(第一个view参数)
    • 在django调用view之前调用该函数
    • 返回None(将继续处理请求,执行其他中间件提供的process_view函数,并且核心的view函数)、或者HttpResponse对象(将不再调用下面的流程,将返回结果到前端)

    5.2. process_exception():

    process_exception(request, exception)

    • request:请求对象,exception: view函数抛出的一次对象
    • 当一个view抛出了异常后,将调用该函数
    • 返回None(默认异常处理流程)、或者HttpResponse对象(模板响应、中间件响应将被应用上、并且响应结果返回给浏览器)

    5.3. process_template_response():

    process_template_response(request, response)

    • request: 请求对象,response: 由view或者中间件返回的TemplateResponse对象
    • 在view完成执行之后调用该函数。
    • 必须返回一个实现了render方法的响应对象。通过response.template_name, response.context_data来修改传递的响应对象,也可以参加并绑定新的TemplateResponse对象。
    • 不需要明确指定render响应,影响将在所有模板响应中间件完成调用之后自动render。

    5.4. process_request():

    process_request(request)

    • request: 请求对象
    • 这个相当于__call__()中调用self.get_response(request)之前的代码部分
    • process_request和process_response要生效必须在__call__中明确指定调用,也可以通过继承:MiddlewareMixin类来隐式调用这两个方法。
    class MiddlewareMixin(object):
        def __init__(self, get_response):
            self.get_response = get_response
            super(MiddlewareMixin, self).__init__()
    
        def __call__(self, request):
            response = None
            if hasattr(self, 'process_request'):
                response = self.process_request(request)
            if not response:
                response = self.get_response(request)
            if hasattr(self, 'process_response'):
                response = self.process_response(request, response)
            return response

    5.5. process_response():

    process_response(request, response)

    • request: 请求对象,response: 响应对象
    • 这个相当于把self.get_response(request)返回的response对象,和reques对象传递给该函数,该函数在self.get_response(request)之后执行。
  • 相关阅读:
    2019.9.25 初级数据结构——树状数组
    2019.9.29 陪审团
    2019.9.27 硬币
    0070-星星阵
    0069-简单的回文数问题
    0068-简单的求和问题
    0067-水仙花数
    0066-若干个数求和问题
    0065-数方块
    0064-简单的平方和
  • 原文地址:https://www.cnblogs.com/timlinux/p/9253497.html
Copyright © 2011-2022 走看看