Django中间件是一种在请求和响应处理过程中介入的机制,允许你在视图处理请求之前或之后执行自定义代码。中间件适用于处理全局性任务,如身份验证、日志记录、内容修改等。以下是Django中间件的详细说明和使用方法:
一、中间件的核心概念
-
作用阶段:
• 请求阶段:在路由到视图之前处理请求(如身份验证)。
• 视图阶段:在调用视图前后执行操作(如权限检查)。
• 响应阶段:在返回响应前修改内容(如添加HTTP头)。
• 异常阶段:处理视图或中间件抛出的异常(如统一错误处理)。 -
中间件类方法:
•process_request(request)
: 在路由到视图前调用。
•process_view(request, view_func, view_args, view_kwargs)
: 在视图被调用前执行。
•process_response(request, response)
: 在所有响应返回前处理。
•process_exception(request, exception)
: 处理视图抛出的异常。
•process_template_response(request, response)
: 处理模板响应(如修改上下文)。
二、创建自定义中间件
1. 编写中间件类
python"># myapp/middleware/custom_middleware.py
import logging
from django.http import HttpResponseForbiddenlogger = logging.getLogger(__name__)class SimpleLoggingMiddleware:"""记录请求日志的中间件"""def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):# 请求处理前logger.info(f"Request started: {request.method} {request.path}")response = self.get_response(request) # 继续处理链# 响应处理后logger.info(f"Request finished: {request.method} {request.path} → {response.status_code}")return responseclass IPFilterMiddleware:"""过滤非法IP的中间件"""def __init__(self, get_response):self.get_response = get_responseself.allowed_ips = ['127.0.0.1', '192.168.1.0/24'] # 允许的IP或网段def __call__(self, request):client_ip = request.META.get('REMOTE_ADDR')if not self._is_ip_allowed(client_ip):return HttpResponseForbidden("IP地址被禁止访问")return self.get_response(request)def _is_ip_allowed(self, ip):# 简单示例:实际可能需要更复杂的IP检查逻辑return ip in self.allowed_ips
2. 配置中间件
在 settings.py
的 MIDDLEWARE
列表中注册中间件:
python"># settings.py
MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','myapp.middleware.custom_middleware.SimpleLoggingMiddleware', # 自定义中间件'myapp.middleware.custom_middleware.IPFilterMiddleware', # 另一个中间件
]
执行顺序:
• 中间件按列表顺序从上到下处理请求(process_request
)。
• 响应阶段按从下到上的顺序处理(process_response
)。
三、中间件的常见应用场景
1. 请求日志记录
记录每个请求的路径、方法、耗时等信息:
python">class RequestTimingMiddleware: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"Request to {request.path} took {duration:.2f} seconds")return response
2. 用户认证增强
检查特定Header或Token:
python">class APITokenMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):if not request.user.is_authenticated:token = request.headers.get('Authorization', '').split('Bearer ')[-1]if token == 'SECRET_API_KEY':# 模拟用户登录(示例逻辑)request.user = get_user_model().objects.get(username='api_user')return self.get_response(request)
3. 跨域请求处理(CORS)
手动添加CORS头(或使用第三方库如 django-cors-headers
):
python">class CustomCorsMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):response = self.get_response(request)response['Access-Control-Allow-Origin'] = '*'response['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'response['Access-Control-Allow-Headers'] = 'Content-Type'return response
4. 响应内容修改
压缩响应或替换敏感信息:
python">import gzipclass GzipResponseMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):response = self.get_response(request)if 'gzip' in request.headers.get('Accept-Encoding', ''):response.content = gzip.compress(response.content)response['Content-Encoding'] = 'gzip'return response
四、中间件的注意事项
-
性能影响:
• 避免在中间件中执行耗时操作(如数据库查询),否则会拖慢所有请求。
• 使用缓存优化频繁访问的数据(如用户权限信息)。 -
异常处理:
• 在process_exception
中捕获异常时,需返回None
以继续传递异常。
• 生产环境中应记录错误日志而非暴露堆栈信息。 -
中间件顺序:
• 安全中间件(如SecurityMiddleware
)通常应放在最前面。
• 依赖其他中间件的组件(如SessionMiddleware
需在认证中间件之前)。 -
测试中间件:
• 使用Django测试客户端模拟请求,验证中间件行为:python">from django.test import RequestFactory, TestCaseclass TestMiddleware(TestCase):def test_ip_filter(self):factory = RequestFactory()request = factory.get('/', REMOTE_ADDR='192.168.1.5')middleware = IPFilterMiddleware(lambda r: None)response = middleware(request)self.assertEqual(response.status_code, 403) # 假设该IP被禁止
五、中间件与其他组件的对比
组件 | 用途 | 作用范围 |
---|---|---|
中间件 | 全局请求/响应处理(如日志、认证) | 所有HTTP请求 |
信号(Signal) | 响应特定事件(如保存模型后触发操作) | 应用内部事件 |
上下文处理器 | 向模板添加全局变量(如当前用户) | 模板渲染阶段 |
六、总结
Django中间件是处理HTTP请求和响应流程的核心机制,适用于以下场景:
• 全局功能:如日志、IP过滤、性能监控。
• 请求预处理:用户认证、数据解析。
• 响应后处理:修改响应头、压缩内容。
• 异常统一处理:记录错误、返回友好提示。
通过合理设计中间件,可以解耦代码并增强应用的可维护性。但需谨慎设计以避免性能瓶颈和逻辑混乱。