当前位置: 首页 > news >正文

【Django】中间件

Django 中间件是 Django 框架里一个轻量级、可插拔的组件,它能在全局范围内对 Django 的请求和响应进行处理。中间件处于 Django 的请求处理流程之中,在请求抵达视图函数之前以及视图函数返回响应之后执行特定操作。以下是关于 Django 中间件的详细介绍:

一、详细介绍

工作原理

Django 中间件的工作流程是一个请求/响应处理的管道。当一个请求到达 Django 项目时,它会依次经过每个中间件的处理,这些处理可能包括对请求进行预处理、身份验证、日志记录等。在视图函数处理完请求并返回响应后,响应会再次经过中间件,不过这次是反向顺序,中间件可以对响应进行后处理,如添加响应头、压缩响应内容等。

中间件的作用

  1. 全局请求处理:可以对所有请求进行预处理,例如验证用户身份、检查请求来源等。
  2. 全局响应处理:对所有响应进行后处理,如添加通用的响应头、压缩响应内容等。
  3. 异常处理:捕获视图函数中抛出的异常,并进行统一处理。
  4. 性能监控:记录请求的处理时间,方便进行性能分析。

中间件的使用场景

  1. 身份验证和授权:在请求到达视图之前验证用户身份,确保只有授权用户可以访问某些视图。
  2. 日志记录:记录每个请求的详细信息,如请求时间、请求路径、请求参数等,方便后续的调试和分析。
  3. 缓存控制:设置响应头,控制浏览器和缓存服务器对响应的缓存策略。
  4. 跨域资源共享(CORS):处理跨域请求,允许不同域名的页面访问当前网站的资源。

中间件的实现方式

在 Django 中,中间件可以通过以下几种方式实现:

函数式中间件

函数式中间件是最简单的中间件实现方式,它是一个接受 get_response 函数作为参数的函数,返回一个新的函数,该函数处理请求和响应。

def simple_middleware(get_response):def middleware(request):# 请求处理前的逻辑print("Before view is called")response = get_response(request)# 请求处理后的逻辑print("After view is called")return responsereturn middleware
类式中间件

类式中间件是更灵活的实现方式,它通过定义一个类来实现中间件的功能。类中需要实现 __init____call__ 方法。

class SimpleMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):# 请求处理前的逻辑print("Before view is called")response = self.get_response(request)# 请求处理后的逻辑print("After view is called")return response

中间件的配置

要使用自定义的中间件,需要将其添加到 Django 项目的 settings.py 文件中的 MIDDLEWARE 设置中。中间件的顺序很重要,请求会按照 MIDDLEWARE 列表中的顺序依次经过每个中间件,而响应则会按照相反的顺序经过中间件。

MIDDLEWARE = [# 其他中间件...'myapp.middleware.SimpleMiddleware',
]

内置中间件

Django 提供了一些内置的中间件,这些中间件可以直接在项目中使用,常见的内置中间件包括:

  • django.middleware.security.SecurityMiddleware:提供一些基本的安全功能,如安全头设置、HTTP 严格传输安全(HSTS)等。
  • django.contrib.sessions.middleware.SessionMiddleware:处理会话功能,允许在不同请求之间存储和访问用户数据。
  • django.contrib.auth.middleware.AuthenticationMiddleware:将用户对象附加到每个请求上,方便在视图中使用 request.user 来获取当前用户。
  • django.middleware.csrf.CsrfViewMiddleware:提供跨站请求伪造(CSRF)保护。

通过使用中间件,你可以在不修改视图函数的情况下,对整个 Django 项目的请求和响应进行统一处理,提高代码的可维护性和复用性。


二、多个中间件的执行顺序

Django 中间件的执行顺序是理解其工作原理的关键部分,下面为你详细且形象地介绍多个中间件的执行顺序。

整体流程概述

当一个请求进入 Django 应用时,它会像一个“旅行者”一样,依次经过 MIDDLEWARE 设置列表里的各个中间件,这个过程就像是旅行者依次穿过不同的“关卡”。在每个关卡,中间件可以对请求进行检查、修改等操作。当请求到达视图函数并得到响应后,响应又会沿着相反的方向,再次穿过这些“关卡”,只不过这次是从最后一个中间件开始,逐个往前处理,每个中间件可以对响应进行后处理。

执行顺序的形象比喻

假设你要去一个神秘的城堡参观,这个城堡有很多道“魔法门”,每道魔法门都有不同的魔法效果,这些魔法门就相当于 Django 中的中间件。

请求阶段

当你从城堡外走向城堡内部(请求进入)时,你需要依次穿过这些魔法门。每穿过一道门,门的魔法就会作用在你身上,比如给你一个特殊的标记、检查你的身份等。这个过程就如同请求依次经过 MIDDLEWARE 列表中的中间件,每个中间件对请求进行预处理。

视图处理阶段

当你穿过所有的魔法门后,就进入了城堡的核心区域(视图函数),在这里你可以完成你的参观任务(处理请求),并得到一些纪念品(生成响应)。

响应阶段

当你参观结束,要离开城堡时,你需要再次穿过这些魔法门,但这次是反向的。每穿过一道门,魔法门又会对你身上的纪念品进行一些处理,比如给纪念品添加一个封印、改变纪念品的外观等。这个过程就如同响应依次经过中间件,每个中间件对响应进行后处理。

代码示例与执行顺序说明

假设我们有三个中间件 MiddlewareAMiddlewareBMiddlewareC,并且在 settings.py 中的 MIDDLEWARE 设置如下:

MIDDLEWARE = ['myapp.middleware.MiddlewareA','myapp.middleware.MiddlewareB','myapp.middleware.MiddlewareC',
]

下面是这三个中间件的简单实现:

# myapp/middleware.py
class MiddlewareA:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):print("MiddlewareA: Before view")response = self.get_response(request)print("MiddlewareA: After view")return responseclass MiddlewareB:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):print("MiddlewareB: Before view")response = self.get_response(request)print("MiddlewareB: After view")return responseclass MiddlewareC:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):print("MiddlewareC: Before view")response = self.get_response(request)print("MiddlewareC: After view")return response

当一个请求到达时,控制台的输出顺序如下:

MiddlewareA: Before view
MiddlewareB: Before view
MiddlewareC: Before view
# 视图函数处理请求
MiddlewareC: After view
MiddlewareB: After view
MiddlewareA: After view

从输出可以看出,请求按照 MIDDLEWARE 列表中的顺序依次经过 MiddlewareAMiddlewareBMiddlewareC 的“请求预处理”部分,然后进入视图函数处理请求。视图函数返回响应后,响应按照相反的顺序经过 MiddlewareCMiddlewareBMiddlewareA 的“响应后处理”部分。

顺序的重要性

中间件的顺序非常重要,因为它会影响到中间件的执行效果。例如,身份验证中间件通常需要放在其他需要用户身份信息的中间件之前,这样才能确保在后续中间件执行时,用户身份已经验证通过。如果顺序设置不当,可能会导致中间件无法正常工作,或者出现安全漏洞。

综上所述,理解 Django 中间件的执行顺序对于正确使用中间件和构建高效的 Django 应用至关重要。


三、MiddlewareMixin

MiddlewareMixin 是 Django 框架里的一个实用工具类,它的主要作用是简化中间件的创建过程。下面从多个方面对其进行详细介绍。

用途

在 Django 早期版本中,创建中间件的方式较为复杂,需要手动处理中间件的初始化和请求响应的调用逻辑。而 MiddlewareMixin 则是 Django 为了简化中间件的编写而引入的一个基类,借助它能够更便捷地创建中间件。

工作原理

MiddlewareMixin 是一个实现了特定逻辑的基类,它提供了中间件所需的基本结构。当你让自定义中间件继承自 MiddlewareMixin 时,就能利用其已经实现好的初始化和请求响应处理逻辑,从而减少代码量。

使用方法

以下是使用 MiddlewareMixin 创建中间件的示例:

from django.utils.deprecation import MiddlewareMixinclass SimpleMiddleware(MiddlewareMixin):def process_request(self, request):# 请求处理前的逻辑print("Before view is called")def process_response(self, request, response):# 请求处理后的逻辑print("After view is called")return response

在这个例子里,SimpleMiddleware 继承自 MiddlewareMixin,并且实现了两个方法:

  • process_request(request):此方法会在请求到达视图之前被调用,可用于对请求进行预处理,像验证用户身份、记录请求日志等操作。
  • process_response(request, response):该方法会在视图返回响应之后被调用,可用于对响应进行后处理,比如添加响应头、压缩响应内容等操作。

完整示例

假设你要在项目中使用这个中间件,需要完成以下步骤:

  1. 创建中间件文件:在你的应用(例如 myapp)下创建一个 middleware.py 文件,并把上述中间件代码添加进去。
  2. 配置中间件:在 settings.py 文件的 MIDDLEWARE 设置里添加自定义中间件的路径。
MIDDLEWARE = [# 其他中间件...'myapp.middleware.SimpleMiddleware',
]

注意事项

  • Django 版本差异:在 Django 1.10 及之后的版本中,MiddlewareMixin 被用来兼容旧的中间件写法。从 Django 2.0 开始,中间件可以通过实现 __call__ 方法来创建,这种方式更为简洁。示例如下:
class NewStyleMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):# 请求处理前的逻辑print("Before view is called")response = self.get_response(request)# 请求处理后的逻辑print("After view is called")return response
  • 执行顺序:中间件的执行顺序由 MIDDLEWARE 设置列表中的顺序决定。请求会按照列表顺序依次经过各个中间件的 process_request 方法,而响应则会按照相反顺序经过各个中间件的 process_response 方法。

总结

MiddlewareMixin 是 Django 提供的一个用于简化中间件编写的工具类,它让开发者可以通过实现 process_requestprocess_response 方法来创建中间件。不过,随着 Django 版本的更新,新的中间件创建方式逐渐流行,你可以根据项目需求和 Django 版本选择合适的方式。

http://www.xdnf.cn/news/317269.html

相关文章:

  • 软件工程(三):模块的内聚模型
  • 如何在大型项目中解决 VsCode 语言服务器崩溃的问题
  • 政务浏览器 一站式首页功能配置说明
  • 极狐GitLab 命名空间的类型有哪些?
  • css animation 动画属性
  • 华为昇腾910B通过vllm部署InternVL3-8B教程
  • 大模型系列(五)--- GPT3: Language Models are Few-Shot Learners
  • IPFS集群部署
  • Linux/AndroidOS中进程间的通信线程间的同步 - 信号量
  • Java游戏服务器开发流水账(1)游戏服务器的架构浅析
  • Wireshark抓账号密码
  • 一文走进GpuGeek | conda常用命令
  • Prompt(提示词)工程师,“跟AI聊天”
  • Java版ERP管理系统源码(springboot+VUE+Uniapp)
  • FID和IS的区别
  • STM32裸机开发问题汇总
  • (1-1)Java的JDK、JRE、JVM三者间的关系
  • 淘宝按图搜索商品(拍立淘)爬虫实战指南
  • 技术视界|青龙机器人训练地形详解(二):添加地形到训练环境
  • 光伏“531”政策倒逼下,光储充一体化系统如何破解分布式光伏收益困局?
  • sql错题(3)
  • 学习记录:DAY23
  • 发那科机器人3(机器人编程基础)
  • Python小酷库系列:5个常用的dict属性化访问扩展库
  • Kubernetes调度技术:污点与容忍生产级应用指南
  • Selenium使用指南
  • 7.2.安全防御
  • 一个项目的周测试的文档(Billing Service 测试文档)
  • pcie协议复位
  • 1688拍立淘搜索相似商品API接口概述,json数据示例参考