Django 3.2自定义中间件计算变量并传递至所有视图的实现方法
问题根源
你当前的代码存在两个会直接导致取值失败的硬伤:
- 变量赋值位置错误:你将
mysecret_value的赋值逻辑写在response = self.get_response(request)代码之后,这段逻辑是视图执行完成、生成响应后才会运行的,等代码执行到赋值语句时,视图逻辑已经跑完了,根本赶不上取值时机 - 不存在跨作用域的变量共享:中间件
__call__方法内定义的局部变量,和视图函数的作用域完全隔离,没有办法直接跨函数传递使用
实现方案
Django的请求处理链路中,同一个请求对应的request对象会从最早执行的中间件开始,全程透传到所有后续执行的中间件、视图、模板渲染环节。你只需要把计算得到的值挂载到这个request对象的自定义属性上,所有后续环节都能直接读取这个值,不需要额外引入全局变量或者持久化存储。
修改自定义中间件
把计算变量的逻辑前移到视图执行前的位置,再将计算值绑定到request对象上,修改后的代码如下:
class MyCustomMiddleware: def __init__(self, get_response): self.get_response = get_response # 服务启动时执行一次的初始化逻辑可以写在这里 def __call__(self, request): # 视图执行前的逻辑统一写在这个代码块里 mysecret_value = 4269 # 将计算完成的值挂载到request的自定义属性上 request.mysecret_value = mysecret_value # 触发后续链路执行:依次运行其他后置中间件、目标视图,最终拿到响应 response = self.get_response(request) # 视图执行完成后的逻辑写在这里(这部分运行时视图已经执行完毕,无法在这里给视图传递值) return response
视图中读取变量
视图函数的入参本身就是这个全程透传的request对象,直接读取之前挂载的自定义属性即可,修改后的视图代码:
def foobar(request): # 直接从request对象上读取中间件挂载的变量 the_value = request.mysecret_value # 后续业务逻辑正常编写
注意事项
- 自定义挂载的属性名不要和Django request对象的原生属性重名,避免覆盖原有功能引发异常
- 检查settings.py中
MIDDLEWARE配置列表里MyCustomMiddleware的位置,保证它的执行时机早于所有需要用到mysecret_value的视图,避免出现还没完成属性赋值就进入视图的情况
内容的提问来源于stack exchange,提问作者Homunculus Reticulli
相关产品推荐
相关产品推荐

