Django 非继承MiddlewareMixin中间件开发指南

一、新旧实现方式对比

标准实现(需MiddlewareMixin)

from django.utils.deprecation import MiddlewareMixin

class StandardMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 请求预处理
        pass

原生实现(无需MiddlewareMixin)

class NativeMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # 请求预处理
        response = self.get_response(request)
        # 响应后处理
        return response

二、完整实现步骤

1. 基本结构搭建

class RawMiddleware:
    """原生中间件模板"""
    
    def __init__(self, get_response):
        # 初始化时接收get_response
        self.get_response = get_response
        # 🏷️ 可在此初始化全局配置
        self.cache = caches['default']
    
    def __call__(self, request):
        """核心调用方法"""
        # 请求预处理逻辑
        if not self._pre_check(request):
            return HttpResponseForbidden()
        
        # 调用后续中间件链
        response = self.get_response(request)
        
        # 响应后处理逻辑
        response = self._post_process(response)
        
        return response
    
    def _pre_check(self, request):
        """自定义预处理方法"""
        return request.user.is_authenticated
    
    def _post_process(self, response):
        """自定义后处理方法"""
        response.headers['X-Middleware'] = 'RawMiddleware'
        return response

三、钩子方法扩展实现

1. 实现process_view

class ViewAwareMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        response = self.get_response(request)
        return response
    
    def process_view(self, request, view_func, view_args, view_kwargs):
        """视图预处理"""
        # 记录视图访问日志
        logger.info(
            f"Accessing {view_func.__name__} "
            f"with args: {view_args} kwargs: {view_kwargs}"
        )
        
        # 动态修改视图参数
        if 'page_size' in view_kwargs:
            view_kwargs['page_size'] = min(
                view_kwargs['page_size'], 100
            )

2. 异常处理实现

class ExceptionHandlingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        try:
            return self.get_response(request)
        except Exception as e:
            return self.handle_exception(request, e)
    
    def handle_exception(self, request, exception):
        """统一异常处理"""
        if isinstance(exception, DatabaseError):
            return HttpResponseServerError("数据库服务异常")
        
        # 生产环境返回通用错误
        if not settings.DEBUG:
            return JsonResponse(
                {'error': '系统内部错误'}, 
                status=500
            )
        
        # 开发环境显示详细信息
        return JsonResponse(
            {'error': str(exception)},
            status=500
        )

四、完整生命周期控制

1. 全钩子中间件示例

class FullLifecycleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # 请求预处理
        if self.process_request(request) is not None:
            return self.process_request(request)
        
        # 执行视图预处理
        response = self.get_response(request)
        
        # 响应后处理
        return self.process_response(request, response)
    
    def process_request(self, request):
        """自定义请求处理"""
        if 'blacklist' in request.path:
            return HttpResponseForbidden()
        return None
    
    def process_response(self, request, response):
        """自定义响应处理"""
        response.headers['X-Processed-By'] = self.__class__.__name__
        return response
    
    def process_view(self, request, view_func, view_args, view_kwargs):
        """自定义视图处理"""
        if getattr(view_func, 'audit_required', False):
            audit_log(request, 'VIEW_ACCESS')

2. 执行流程图解

Client NativeMiddleware View HTTP Request process_request 直接响应 调用视图 process_view 生成响应 process_response 最终响应 alt [返回响应] [继续处理] Client NativeMiddleware View

五、与标准中间件的差异处理

1. 方法触发差异对比

方法MiddlewareMixin方式原生实现方式
初始化时机每次请求重新实例化服务启动时单例初始化
process_request自动调用需在__call__中手动调用
process_response自动逆序调用需自行控制执行顺序
异常处理依赖process_exception需实现try-catch机制

2. 兼容性处理技巧

class HybridMiddleware:
    """兼容新旧版本的中间件"""
    
    def __init__(self, get_response=None):
        # 兼容旧式中间件写法
        self.get_response = get_response
    
    def __call__(self, request):
        response = self.get_response(request)
        return response
    
    def process_request(self, request):
        """旧式中间件方法"""
        pass
    
    def process_response(self, request, response):
        """旧式中间件方法"""
        return response

六、生产环境实战案例

1. API签名验证中间件

class APISignatureMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.secret_key = settings.API_SECRET
    
    def __call__(self, request):
        # 跳过非API请求
        if not request.path.startswith('/api/'):
            return self.get_response(request)
        
        # 验证签名
        if not self._validate_signature(request):
            return JsonResponse(
                {'error': '无效签名'}, 
                status=401
            )
        
        return self.get_response(request)
    
    def _validate_signature(self, request):
        """签名验证逻辑"""
        timestamp = request.headers.get('X-Timestamp')
        sign = request.headers.get('X-Signature')
        
        raw_str = f"{request.method}{request.path}{timestamp}"
        expect_sign = hmac.new(
            self.secret_key.encode(),
            raw_str.encode(),
            'sha256'
        ).hexdigest()
        
        return hmac.compare_digest(sign, expect_sign)

2. 实时流量监控中间件

class TrafficMonitorMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.stats = {
            'total_requests': 0,
            'api_requests': defaultdict(int)
        }
    
    def __call__(self, request):
        # 统计请求
        self.stats['total_requests'] += 1
        if request.path.startswith('/api/'):
            self.stats['api_requests'][request.path] += 1
        
        # 流量阈值检查
        if self.stats['total_requests'] > 10000:
            return HttpResponseServerError('系统繁忙')
        
        response = self.get_response(request)
        
        # 添加监控头
        response['X-Request-Count'] = self.stats['total_requests']
        return response

七、注意事项

  1. 生命周期控制
    需在__call__方法中显式调用get_response,否则中间件链会中断

  2. 状态保持风险

    # 错误示例:跨请求共享状态
    class BadMiddleware:
        cache = {}  # 类属性会被所有请求共享
        
        def __init__(self, get_response):
            self.get_response = get_response
    
  3. 性能优化建议

    class OptimizedMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
            # 预加载资源
            self.redis_pool = redis.ConnectionPool(max_connections=10)
        
        def __call__(self, request):
            # 复用连接
            request.redis = redis.Redis(
                connection_pool=self.redis_pool
            )
            return self.get_response(request)
    
  4. 测试策略

    from django.test import RequestFactory
    
    def test_middleware_flow():
        factory = RequestFactory()
        request = factory.get('/')
        
        def dummy_view(request):
            return HttpResponse()
        
        middleware = APISignatureMiddleware(dummy_view)
        
        # 测试签名验证
        response = middleware(request)
        assert response.status_code == 401
    

扩展阅读
Django官方中间件文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yant224

点滴鼓励,汇成前行星光🌟

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值