如何在Django 1.11中获取已注册的XYZMiddleware实例?
如何在Django 1.11集成测试中检索已注册的XYZMiddleware实例?
我已经定义了中间件类XYZMiddleware,并且在settings.MIDDLEWARE中完成了注册。这个类的实例包含相关状态,所以在集成测试中,我需要获取Django 1.11创建的XYZMiddleware对象,但主题文档和参考文档都没提到这个方法,请问该怎么检索?
方法1:给中间件添加实例追踪(简单易行)
如果可以修改XYZMiddleware的代码,这是最直接的方案——给类加一个类属性来保存实例引用,测试时直接调用即可:
class XYZMiddleware: # 类属性用于存储测试用的实例引用 _test_instance = None def __init__(self, get_response=None): self.get_response = get_response # 初始化你的业务状态 self.request_count = 0 # 保存当前实例到类属性(可以用DEBUG条件限制只在测试/开发环境生效) XYZMiddleware._test_instance = self def process_request(self, request): # 示例状态更新逻辑 self.request_count += 1 return None
在集成测试里,你只需要这样获取实例:
from django.test import TestCase, Client from yourapp.middleware import XYZMiddleware class MiddlewareStateTest(TestCase): def test_middleware_state_tracking(self): # 发送请求触发中间件初始化(如果还未初始化) client = Client() client.get('/') # 直接拿到实例 middleware = XYZMiddleware._test_instance # 验证状态 self.assertEqual(middleware.request_count, 1)
这种方法的优势是简单直观,对生产环境的影响极小——你甚至可以用if settings.DEBUG or settings.TESTING:来包裹实例赋值的代码,避免在正式环境中运行。
方法2:从Django WSGI Handler中提取实例(无需修改中间件)
如果不想改动中间件代码,我们可以利用Django 1.11的内部实现细节来提取实例。WSGIHandler在初始化时会创建所有中间件实例,并将它们包装在_middleware_chain属性的闭包中。
你可以用这个递归函数来遍历中间件链,找到目标实例:
def find_middleware(chain, target_class): # 检查闭包中的内容,递归查找目标实例 if hasattr(chain, '__closure__'): for cell in chain.__closure__: content = cell.cell_contents if isinstance(content, target_class): return content # 递归检查嵌套的中间件闭包 result = find_middleware(content, target_class) if result is not None: return result return None
然后在测试中这样使用:
from django.test import TestCase, Client from django.core.handlers.wsgi import WSGIHandler from yourapp.middleware import XYZMiddleware class MiddlewareStateTest(TestCase): def test_retrieve_middleware_instance(self): client = Client() # 发送请求确保中间件已初始化 client.get('/') # 获取WSGI Handler实例 handler = WSGIHandler() # 查找目标中间件 middleware = find_middleware(handler._middleware_chain, XYZMiddleware) self.assertIsNotNone(middleware) # 验证状态逻辑 self.assertEqual(middleware.request_count, 1)
注意:这个方法依赖Django的内部实现,升级到更高版本的Django(比如2.0+)后可能会失效,因为后续版本的中间件机制有较大调整。
内容的提问来源于stack exchange,提问作者Lutz Prechelt
相关产品推荐
相关产品推荐

