Django中的中间件(middleware)

本文深入探讨Django中间件的概念,解释如何通过中间件在视图函数前后执行额外操作,实现请求过滤等功能。涵盖中间件的自定义方法,如process_request和process_response,及其在全局请求处理中的作用。

一、middleware(中间件)

1、什么是中间件

  • 问题:如何过滤掉没有登陆就访问其他页面?
    解决方法

    • 使用装饰器(但是我们要过滤的页面很多,这个方法就很不方便了)
    • 使用中间件(使用此方法要注意,中间件是全局操作,所以要慎用)
  • 概念:

    中间件是一个用来处理Django的请求和响应的一个类,可以改变全局范围内Django的输入和输出。简单理解就是中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作。

  • 举个例子:
    中间件就好比火车站的每一层安检,首先检查车票,然后再检查是否携带危险物品,如果车票或者行李不符合要求,就不能坐上火车(目标)。
    由于其影响的是全局,所以需要谨慎使用,使用不当会影响性能。
    (简单理解就是只要设置了中间件,任何请求都会经过中间件)

  • 每个中间件都负责做一些特定的功能。
    在这里插入图片描述

  • 我们从浏览器发出一个请求 Request,得到一个响应后的内容 HttpResponse ,这个请求传递到 Django的过程如下:
    在这里插入图片描述

(二)自定义中间件

  • 中间件五个方法
    中间件可以定义五个方法,分别是:
    process_request(self,request)
    process_view(self, request, view_func, view_args, view_kwargs)
    process_template_response(self,request,response)(不用,自己查阅)
    process_exception(self, request, exception)
    process_response(self, request, response)
    以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户。
    (主要的是process_request和process_response)
  • 定义中间件步骤
    • 创建一个类继承MiddlewareMixin

      from django.utils.deprecation import MiddlewareMixin
      
      #中间件MD1
      class MD1(MiddlewareMixin):
         # 覆写方法
         def process_request(self, request):
            print('MD1...request...')
      
      #中间件MD2
      class MD2(MiddlewareMixin):
      def process_request(self, request):print('MD2...request...')
      
    • 覆写想使用的方法

    • 在setting.py中进行注册
      在这里插入图片描述

  • 方法讲解
    • process_request(self,request)方法
      此方法有一个参数,就是request,这个request和视图函数中的request是同一个。
      此方法的返回值可以是None也可以是HttpResponse对象。
      返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。
      (提示:rander() 函数返回的是HttpResponse对象)

      • 总结:
        (1)中间件的process_request方法是在执行视图函数之前执行的。
        (2)当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的 索引值,从前到后依次执行的。
        (3)不同中间件之间传递的request都是同一个对象 。
    • process_response(request,response)方法
      它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象,response是视图函数返回的对象。该方法必须返回一个响应对象。

      • 响应流程:
        在这里插入图片描述
    • process_view()方法
      process_view(self, request, view_func, view_args, view_kwargs)
      该方法有四个参数
      (1)request是HttpRequest对象。
      (2)view_func是Django即将使用的视图函数。
      (3)view_args是将传递给视图的位置参数的列表.
      (4)view_kwargs是将传递给视图的关键字参数的字典。

      • Django会在调用视图函数之前调用process_view方法。
        它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。
      • 响应流程
        在这里插入图片描述
    • process_exception(self, request, exception)
      该方法两个参数:
      一个HttpRequest对象
      一个exception是视图函数异常产生的Exception对象。
      这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。

<think>我们正在讨论Django中间件。根据引用[1],Django中间件是处理Django请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于全局改变Django的输入或输出。每个中间件组件负责处理特定的功能,例如会话管理、CSRF保护等。中间件的工作原理(引用[2])是:在Django中,每个请求和响应都会通过中间件栈。中间件按照在MIDDLEWARE设置中定义的顺序执行。对于请求,中间件按照从上到下的顺序执行,而对于响应,则按照从下到上的顺序执行中间件的类型(引用[3])主要分为两类:处理请求的中间件(如process_request)和处理响应的中间件(如process_response)。此外,还有process_view、process_exception和process_template_response等方法。使用方法(引用[3])是:首先创建一个中间件类,然后实现需要的方法(如process_request或process_response),最后在settings.py的MIDDLEWARE设置中注册这个中间件。注意中间件的顺序很重要。下面我们详细展开:1.**中间件的作用**:-全局修改请求:例如,在请求到达视图之前,我们可以对请求进行预处理(如添加属性、检查权限等)。-全局修改响应:在视图处理完请求后,我们可以对响应进行后处理(如添加HTTP头、修改响应内容等)。-其他功能:如引用[4]提到的,中间件还可以用于性能优化(缓存计算结果)、安全控制(如引用[5]提到的黑名单过滤)等。2.**中间件的原理**:-当一个HTTP请求到达Django时,首先会经过中间件栈(按MIDDLEWARE列表顺序)的process_request方法。-然后,Django会解析URL找到对应的视图函数。在调用视图函数之前,会经过中间件的process_view方法(按顺序)。-如果视图函数抛出异常,则会触发中间件的process_exception方法(按倒序)。-最后,在返回响应时,会经过中间件的process_response方法(按倒序)。3.**自定义中间件的使用方法**:-创建中间件类:在某个app下创建middleware.py文件,然后定义一个类,例如:```pythonclassSimpleMiddleware:def__init__(self,get_response):self.get_response=get_responsedef__call__(self,request):#在视图调用之前的代码(按中间件顺序执行)response=self.get_response(request)#调用下一个中间件或视图#在视图调用之后的代码(按中间件逆序执行)returnresponse```或者使用更细粒度的方法(如process_request,process_response等)。-注册中间件:在settings.py的MIDDLEWARE列表中添加自定义中间件的路径,例如:`'myapp.middleware.SimpleMiddleware'`。4.**注意事项**(引用[3]和引用[4]):-中间件的顺序非常重要,因为它决定了执行的顺序。-在process_view中修改参数时要小心,避免污染原始视图参数(建议使用深拷贝)。-中间件可以中断请求,直接返回响应(例如在process_request中返回HttpResponse,那么后续中间件和视图将执行)。举例说明:一个记录请求耗时的中间件```pythonimporttimeclassTimingMiddleware:def__init__(self,get_response):self.get_response=get_responsedef__call__(self,request):start_time=time.time()response=self.get_response(request)duration=time.time()-start_timeprint(f"Requestto{request.path}took{duration:.2f}seconds.")#可以添加响应头response['X-Request-Duration']=str(duration)returnresponse```在settings.py中注册:```pythonMIDDLEWARE=[#...其他中间件'myapp.middleware.TimingMiddleware',]```这个中间件会在每个请求处理完成后记录耗时,并在响应头中添加`X-Request-Duration`。总结:Django中间件是一个强大的工具,可以在请求/响应的全局层面进行干预,实现诸如日志记录、权限验证、性能优化等功能。§§相关问题§§1.Django中间件执行顺序是怎样的?2.如何在中间件中处理异常?3.中间件和装饰器有什么区别?4.如何测试Django中间件?5.中间件中哪些方法必须实现?</think>### Django 中间件详解 #### 一、中间件的作用 中间件Django 处理请求/响应流程的核心组件,主要功能包括: 1. **全局请求处理**:在视图执行前拦截请求(如身份验证、CSRF 保护)[^1][^5] 2. **全局响应处理**:在视图执行后修改响应(如添加 HTTP 头、压缩内容) 3. **异常处理**:统一捕获视图抛出的异常[^3] 4. **性能优化**:缓存计算结果、请求耗时统计等[^4] 5. **安全控制**:IP 黑名单过滤、XSS 防护等[^5] #### 二、工作原理 中间件按 `settings.py` 中定义的顺序组成处理链: ```python # settings.py 配置示例 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', # 安全防护 'django.contrib.sessions.middleware.SessionMiddleware', # 会话管理 'django.middleware.common.CommonMiddleware', # URL标准化 'django.middleware.csrf.CsrfViewMiddleware', # CSRF防护 'myapp.middleware.CustomMiddleware', # 自定义中间件 ] ``` **处理流程**: 1. 请求进入时按**从上到下**顺序执行 `process_request()` 方法 2. 执行视图前按顺序执行 `process_view()` 方法[^4] 3. 视图处理请求 4. 响应返回时按**从下到上**顺序执行 `process_response()` 方法 5. 异常发生时按**倒序**执行 `process_exception()` 方法[^3] #### 三、自定义中间件开发 1. **创建中间件类**(在 app 的 middleware.py 中): ```python # myapp/middleware.py import time from copy import deepcopy class PerformanceMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 请求处理前 start_time = time.time() # 调用下一个中间件/视图 response = self.get_response(request) # 响应处理后 duration = time.time() - start_time response.headers['X-Response-Time'] = f'{duration:.2f}s' return response def process_view(self, request, view_func, view_args, view_kwargs): # 深拷贝避免污染原始参数[^4] safe_kwargs = deepcopy(view_kwargs) # 可在此预处理视图参数 return None ``` 2. **注册中间件**: ```python # settings.py MIDDLEWARE = [ ... 'myapp.middleware.PerformanceMiddleware', ] ``` #### 四、关键方法说明 | 方法 | 执行时机 | 返回值作用 | |---------------------|----------------------------|------------------------------| | `process_request` | 请求到达路由前 | 返回 None 继续,返回响应则中断 | | `process_view` | 路由解析后,视图执行前[^4] | 同上 | | `process_response` | 视图返回响应后 | 必须返回响应对象 | | `process_exception` | 视图抛出异常时 | 返回 None 继续,响应则处理异常 | #### 五、最佳实践 1. **顺序敏感**:安全中间件应放在顶部,响应处理中间件放底部[^3] 2. **避免副作用**:在 `process_view` 中修改参数需用深拷贝[^4] 3. **性能优化**:在中间件缓存重复计算结果[^4] ```python class CacheMiddleware: def process_view(self, request, view_func, *args): cache_key = f"view_data:{request.path}" if cached := cache.get(cache_key): return cached # 直接返回缓存响应 return None ``` 4. **异常处理**:统一错误日志记录 ```python class ErrorLoggingMiddleware: def process_exception(self, request, exception): logger.error(f"{request.path} error: {str(exception)}") return None # 交由下一个中间件处理 ``` #### 六、典型应用场景 1. **安全控制**:CSRF 验证、IP 黑名单[^5] 2. **会话管理**:自动绑定用户会话[^2] 3. **性能监控**:请求耗时统计(如上示例) 4. **A/B 测试**:根据请求特征路由到同视图 5. **内容处理**:响应压缩、移动端适配 > 中间件本质是 Django 的插件系统,通过介入请求/响应生命周期实现横切关注点(cross-cutting concerns),避免在视图函数中重复相同逻辑[^1][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值