自定义 Django 中间件

Django 自定义中间件

Django 中间件是一个轻量级、底层的插件系统,可以介入 Django 的请求和响应处理过程,修改 Django 的输入或输出。
定义 Django 中间有以下几种方式:

  1. 定义中间件工厂函数
  2. 定义中间件类
  3. 定义中间件子类, 继承自 MiddlewareMixin

工厂函数

def simple_middleware(get_response):
    print('第一次配置和初始化的时候执行一次')

    def inner(request):
        print('每个请求处理视图前被执行')

        response = get_response(request)

        print('每个请求处理视图之后被执行')

        return response

    return inner

class MyMid:

    def __init__(self, get_response):
        self.get_response = get_response
        
        print('first init')

    def __call__(self, *args, **kwargs):
    
        print('MyMid: process request')
        
        response = self.get_response(*args, **kwargs)
        
        print('MyMid: process response')
        
        return response

子类

子类可实现的方法:

  1. process_request
  2. process_view
  3. process_response
  4. process_template_response
  5. process_exception

继承自 MiddlewareMixin, 不必写 __call____init__ 方法。

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


class MyMiddleware(MiddlewareMixin):

    def process_request(self, request):
        """Request 预处理方法.
        
        Return: 
            None --> 交给下一个中间件继续处理
            HttpResponse() --> 不再执行任何其它的中间件以及相应的 view,  立即返回该 HttpResponse
        """
        print(request.path)
        print('process_request')

    def process_view(self, request, callback, callback_args, callback_kwargs):
        """View 预处理方法.
        Return: 
            None --> Django 将继续处理这个 request, 执行后续的中间件, 然后调用相应的 view
            HttpResponse() --> Django 将不再执行任何其它的中间件以及相应的 view, 立即返回
        """
        print('process_view')
        return None
        # return response

    def process_response(self, request, response):
        """Response 后处理方法.
        Return: 
            必须返回 HttpResponse 对象. 
            可以新生成一个 HttpResponse 对象来返回
        """
        print('process_response')
        return response

    def process_template_response(self, request, response):
        """在模板渲染前执行.
        Return: 
            返回实现了 render 方法的响应对象
        """
        print('process_template_response')
        return response

    def process_exception(self, request, exception):
        """Exception 后处理方法.
        Return: 
            None --> Django 将用框架内置的异常处理机制继续处理相应 request
            HttpResponse() --> Django 将使用该 response,而短路框架内置的异常处理机制
        """
        print('process_exception')
        print('log: ', exception)
        return HttpResponse('Emm, Error!')

注册中间件

"""settings.py"""

MIDDLEWARE = [
    # ...
    
    # 根据实际情况修改路径
    'middlewares.mid_test1.MyMiddleware',
    'middlewares.mid_test2.MyMid',
    'middlewares.mid_test3.simple_middleware',
]

测试中间件方法的调用时机

创建一个 demo 项目, 然后创建一个 app1 应用, 写好主路由和子路由, 建好模板文件, 定义以下视图。

# demo/app1/views.py
from django.http import HttpResponse
from django.template.response import TemplateResponse


def index(request):
    """
    访问视图对应路由时, 类中间件方法的打印顺序:
        process_request
        process_view
        process_response
    """
    return HttpResponse('Hello index.')


def exc(request):
    """
    访问视图对应路由时, 类中间件方法的打印顺序:
        process_request
        process_view
        process_exception
        process_response
    """
    raise


def template(request):
    """
    访问视图对应路由时, 类中间件方法的打印顺序:
        process_request
        process_view
        process_template_response
        process_response
    """
    # 注: 返回 render 结果时不会走类中间件的 process_template_response,
    # 要测试它, 需要返回 TemplateResponse()
    # return render(
    #     request,
    #     'app1/test.html',
    #     context={'data': 'Hello template.'}
    # )
    return TemplateResponse(
        request,
        'app1/test.html',  # 去找 demo/app1/templates/app1/test.html
        context={'data': 'Hello template.'}
    )

中间件的执行顺序

多个中间件的执行顺序

  • 在请求视图被处理前,中间件由上至下依次执行
  • 在请求视图被处理后,中间件由下至上依次执行

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值