Django中间件系统 - 请求处理的拦截器模式

📂 所属阶段:第二部分 — 进阶特性
🎯 难度等级:中级
⏰ 预计学习时间:3-4小时
🎒 前置知识:视图系统与URL路由

目录

中间件概念与工作原理

Django中间件是处理请求和响应的钩子框架,它是一个轻薄的、低级别的插件系统,可以介入Django的请求和响应处理过程。

中间件定义

"""
中间件是Django处理请求/响应的钩子系统,位于:

请求 -> 中间件1 -> 中间件2 -> ... -> 视图 -> 响应
                          <- 中间件2 <- 中间件1 <- 

中间件可以:
1. 在请求到达视图之前处理请求
2. 在视图处理完成后处理响应
3. 在请求/响应过程中修改数据
4. 执行特定的业务逻辑
"""

中间件基本结构

# 自定义中间件的基本结构
class SimpleMiddleware:
    def __init__(self, get_response):
        """
        初始化中间件
        get_response: 下一个中间件或视图函数
        """
        self.get_response = get_response

    def __call__(self, request):
        """
        处理请求和响应的主要方法
        """
        # 请求处理前的逻辑
        print(f"请求前处理: {request.path}")
        
        # 调用下一个中间件或视图
        response = self.get_response(request)
        
        # 响应处理后的逻辑
        print(f"响应后处理: {response.status_code}")
        
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        """
        在Django调用视图之前调用
        返回None或HttpResponse对象
        """
        print(f"即将调用视图: {view_func.__name__}")
        # 可以在这里修改view_kwargs或返回HttpResponse阻止视图执行
        return None

    def process_exception(self, request, exception):
        """
        当视图抛出异常时调用
        """
        print(f"视图异常: {exception}")
        # 可以返回HttpResponse处理异常
        return None

    def process_template_response(self, request, response):
        """
        在视图完成后,模板响应返回前调用
        """
        print("模板响应处理")
        return response

Django中间件架构

中间件执行流程

"""
Django中间件执行流程:

请求阶段:
1. process_request() - 在请求处理前调用
2. process_view() - 在视图调用前调用
3. 视图函数执行
4. process_template_response() - 模板响应处理
5. process_response() - 在响应返回给客户端前调用

异常处理:
- 如果视图引发异常,process_exception()会被调用
- 如果中间件引发异常,后续中间件的process_request不会被调用
"""

# 中间件执行顺序示例
class OrderTestMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        print("OrderTestMiddleware.__init__()")

    def __call__(self, request):
        print("OrderTestMiddleware.__call__(): 请求前")
        
        response = self.get_response(request)
        
        print("OrderTestMiddleware.__call__(): 响应后")
        return response

    def process_request(self, request):
        print("OrderTestMiddleware.process_request()")
        return None

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("OrderTestMiddleware.process_view()")
        return None

    def process_response(self, request, response):
        print("OrderTestMiddleware.process_response()")
        return response

    def process_exception(self, request, exception):
        print("OrderTestMiddleware.process_exception()")
        return None

    def process_template_response(self, request, response):
        print("OrderTestMiddleware.process_template_response()")
        return response

中间件配置

# settings.py - 中间件配置
MIDDLEWARE = [
    # 安全相关中间件
    'django.middleware.security.SecurityMiddleware',
    
    # 会话中间件
    'django.contrib.sessions.middleware.SessionMiddleware',
    
    # 公共中间件
    'django.middleware.common.CommonMiddleware',
    
    # CSRF保护中间件
    'django.middleware.csrf.CsrfViewMiddleware',
    
    # 认证中间件
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    
    # 消息中间件
    'django.contrib.messages.middleware.MessageMiddleware',
    
    # 静态文件中间件
    'django.middleware.staticfiles.StaticFilesMiddleware',
    
    # 点击劫持防护中间件
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    
    # 自定义中间件(通常放在最后)
    'myapp.middleware.CustomMiddleware',
]

# 中间件执行顺序很重要,靠前的中间件会先处理请求,后处理响应

内置中间件详解

SecurityMiddleware

"""
SecurityMiddleware - 安全中间件
功能:提供各种安全相关的HTTP头设置
"""

# 安全配置示例
SECURE_HSTS_SECONDS = 31536000  # HSTS头设置
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_SSL_REDIRECT = True
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_REDIRECT_EXEMPT = []
SECURE_REFERRER_POLICY = 'same-origin'
SECURE_CROSS_ORIGIN_OPENER_POLICY = 'same-origin'

# 会话安全设置
SESSION_COOKIE_SECURE = True  # HTTPS环境下
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Strict'

SessionMiddleware

"""
SessionMiddleware - 会话中间件
功能:处理用户会话
"""

# 会话配置
SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # 数据库会话
SESSION_COOKIE_AGE = 1209600  # 会话有效期(秒)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # 浏览器关闭时过期
SESSION_SAVE_EVERY_REQUEST = True  # 每次请求都保存会话
SESSION_COOKIE_NAME = 'sessionid'
SESSION_COOKIE_DOMAIN = None
SESSION_COOKIE_PATH = '/'
SESSION_COOKIE_SECURE = True  # HTTPS环境下
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Strict'

CsrfViewMiddleware

"""
CsrfViewMiddleware - CSRF保护中间件
功能:防止跨站请求伪造攻击
"""

# CSRF配置
CSRF_COOKIE_NAME = 'csrftoken'
CSRF_COOKIE_AGE = 31449600  # 一年
CSRF_COOKIE_PATH = '/'
CSRF_COOKIE_DOMAIN = None
CSRF_COOKIE_SECURE = True  # HTTPS环境下
CSRF_COOKIE_HTTPONLY = False  # 需要在JavaScript中访问
CSRF_COOKIE_SAMESITE = 'Strict'
CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
CSRF_TRUSTED_ORIGINS = [
    'https://yourdomain.com',
    'https://www.yourdomain.com',
]
CSRF_USE_SESSIONS = False  # 是否使用会话存储CSRF令牌

AuthenticationMiddleware

"""
AuthenticationMiddleware - 认证中间件
功能:将用户信息附加到请求对象
"""

# 认证中间件的工作原理
"""
1. 在请求对象上设置request.user属性
2. 如果用户已认证,request.user是User对象
3. 如果用户未认证,request.user是AnonymousUser对象
4. 设置request.session属性用于会话管理
"""

自定义中间件开发

日志记录中间件

# myapp/middleware/logging_middleware.py
import logging
import time
from django.utils.deprecation import MiddlewareMixin

logger = logging.getLogger(__name__)

class LoggingMiddleware(MiddlewareMixin):
    """请求日志记录中间件"""
    
    def process_request(self, request):
        """记录请求信息"""
        request.start_time = time.time()
        
        logger.info(
            f"REQUEST: {request.method} {request.get_full_path()} "
            f"from {self.get_client_ip(request)}"
        )
        
        # 记录请求头信息
        headers_info = {
            'user_agent': request.META.get('HTTP_USER_AGENT'),
            'referer': request.META.get('HTTP_REFERER'),
            'accept_language': request.META.get('HTTP_ACCEPT_LANGUAGE'),
        }
        
        logger.debug(f"Request headers: {headers_info}")
        
        return None
    
    def process_response(self, request, response):
        """记录响应信息"""
        if hasattr(request, 'start_time'):
            duration = time.time() - request.start_time
            logger.info(
                f"RESPONSE: {request.method} {request.get_full_path()} "
                f"Status: {response.status_code} "
                f"Duration: {duration:.3f}s"
            )
        
        return response
    
    def process_exception(self, request, exception):
        """记录异常信息"""
        logger.error(
            f"EXCEPTION: {request.method} {request.get_full_path()} "
            f"Exception: {str(exception)}",
            exc_info=True
        )
        return None
    
    def get_client_ip(self, request):
        """获取客户端IP地址"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip

性能监控中间件

# myapp/middleware/performance_middleware.py
import time
import psutil
import os
from django.utils.deprecation import MiddlewareMixin
from django.conf import settings

class PerformanceMonitoringMiddleware(MiddlewareMixin):
    """性能监控中间件"""
    
    def process_request(self, request):
        """请求开始时记录系统状态"""
        request.start_time = time.time()
        request.start_memory = self.get_memory_usage()
        
        return None
    
    def process_response(self, request, response):
        """响应完成时记录性能指标"""
        if hasattr(request, 'start_time'):
            duration = time.time() - request.start_time
            
            # 计算内存变化
            end_memory = self.get_memory_usage()
            memory_diff = end_memory - request.start_memory
            
            # 记录性能指标
            perf_data = {
                'duration': duration,
                'memory_used': memory_diff,
                'status_code': response.status_code,
                'url': request.get_full_path(),
                'method': request.method
            }
            
            # 输出性能日志(生产环境中可以发送到监控系统)
            if duration > getattr(settings, 'SLOW_REQUEST_THRESHOLD', 1.0):
                print(f"SLOW REQUEST: {perf_data}")
            
            # 可以将性能数据发送到监控系统
            self.log_performance(perf_data)
        
        return response
    
    def get_memory_usage(self):
        """获取当前进程内存使用量"""
        process = psutil.Process(os.getpid())
        return process.memory_info().rss
    
    def log_performance(self, perf_data):
        """记录性能数据"""
        # 这里可以集成APM工具如New Relic、Datadog等
        print(f"Performance: {perf_data}")

跨域资源共享(CORS)中间件

# myapp/middleware/cors_middleware.py
from django.utils.deprecation import MiddlewareMixin

class CORSMiddleware(MiddlewareMixin):
    """CORS中间件"""
    
    def process_response(self, request, response):
        """添加CORS头"""
        # 允许的来源(生产环境中应该配置白名单)
        allowed_origins = getattr(
            self, 'allowed_origins', 
            ['http://localhost:3000', 'https://yourdomain.com']
        )
        
        origin = request.META.get('HTTP_ORIGIN')
        if origin and origin in allowed_origins:
            response["Access-Control-Allow-Origin"] = origin
        
        # 允许的HTTP方法
        response["Access-Control-Allow-Methods"] = "GET, POST, PUT, PATCH, DELETE, OPTIONS"
        
        # 允许的请求头
        response["Access-Control-Allow-Headers"] = (
            "Content-Type, Authorization, X-Requested-With, "
            "X-CSRFToken, Accept, Origin"
        )
        
        # 允许携带凭证
        response["Access-Control-Allow-Credentials"] = "true"
        
        # 预检请求缓存时间
        response["Access-Control-Max-Age"] = "86400"  # 24小时
        
        return response

class AdvancedCORSMiddleware(MiddlewareMixin):
    """高级CORS中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response
        self.allowed_origins = getattr(
            self, 'allowed_origins', 
            ['http://localhost:3000', 'https://yourdomain.com']
        )
        self.allowed_methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']
        self.allowed_headers = [
            'Content-Type', 'Authorization', 'X-Requested-With',
            'X-CSRFToken', 'Accept', 'Origin'
        ]
    
    def __call__(self, request):
        # 处理预检请求
        if request.method == 'OPTIONS':
            response = self.handle_preflight_request(request)
            return response
        
        response = self.get_response(request)
        return self.add_cors_headers(request, response)
    
    def handle_preflight_request(self, request):
        """处理预检请求"""
        origin = request.META.get('HTTP_ORIGIN')
        
        if origin and origin in self.allowed_origins:
            response = HttpResponse()
            response["Access-Control-Allow-Origin"] = origin
            response["Access-Control-Allow-Methods"] = ", ".join(self.allowed_methods)
            response["Access-Control-Allow-Headers"] = ", ".join(self.allowed_headers)
            response["Access-Control-Max-Age"] = "86400"
            return response
        
        return HttpResponse(status=403)
    
    def add_cors_headers(self, request, response):
        """添加CORS头到响应"""
        origin = request.META.get('HTTP_ORIGIN')
        
        if origin and origin in self.allowed_origins:
            response["Access-Control-Allow-Origin"] = origin
            response["Access-Control-Allow-Credentials"] = "true"
        
        return response

用户活动追踪中间件

# myapp/middleware/user_activity_middleware.py
from django.utils.deprecation import MiddlewareMixin
from django.contrib.auth.models import User
from myapp.models import UserActivity  # 假设有一个用户活动模型

class UserActivityMiddleware(MiddlewareMixin):
    """用户活动追踪中间件"""
    
    # 不需要记录的URL模式
    EXCLUDE_PATHS = [
        '/static/',
        '/media/',
        '/admin/jsi18n/',
        '/favicon.ico',
    ]
    
    def process_request(self, request):
        """处理请求前的逻辑"""
        # 检查是否需要记录此请求
        if self.should_record_activity(request):
            request.start_time = time.time()
        
        return None
    
    def process_response(self, request, response):
        """处理响应后的逻辑"""
        if (hasattr(request, 'start_time') and 
            request.user.is_authenticated and 
            response.status_code < 400):
            
            duration = time.time() - request.start_time
            
            # 记录用户活动
            UserActivity.objects.create(
                user=request.user,
                path=request.path,
                method=request.method,
                duration=duration,
                ip_address=self.get_client_ip(request),
                user_agent=request.META.get('HTTP_USER_AGENT', ''),
                referer=request.META.get('HTTP_REFERER', ''),
                status_code=response.status_code
            )
        
        return response
    
    def should_record_activity(self, request):
        """判断是否需要记录活动"""
        path = request.path
        
        # 检查是否在排除路径中
        for exclude_path in self.EXCLUDE_PATHS:
            if path.startswith(exclude_path):
                return False
        
        # 检查是否是静态文件请求
        if path.endswith(('.css', '.js', '.png', '.jpg', '.jpeg', '.gif', '.ico')):
            return False
        
        return True
    
    def get_client_ip(self, request):
        """获取客户端IP地址"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip

中间件执行顺序

执行顺序详解

"""
中间件执行顺序:

MIDDLEWARE = [
    'middleware1',  # 1. 请求:最先执行, 响应:最后执行
    'middleware2',  # 2. 请求:第二执行, 响应:倒数第二执行
    'middleware3',  # 3. 请求:最后执行, 响应:最先执行
    'view',         # 4. 视图执行
]

执行流程:
请求阶段:
middleware1.process_request() -> middleware2.process_request() -> 
middleware3.process_request() -> view() -> 
middleware3.process_response() -> middleware2.process_response() ->
middleware1.process_response()
"""

# 示例:不同顺序的影响
class OrderA:
    def __init__(self, get_response):
        self.get_response = get_response
        print("OrderA.__init__()")
    
    def __call__(self, request):
        print("OrderA.__call__() - 请求前")
        response = self.get_response(request)
        print("OrderA.__call__() - 响应后")
        return response

class OrderB:
    def __init__(self, get_response):
        self.get_response = get_response
        print("OrderB.__init__()")
    
    def __call__(self, request):
        print("OrderB.__call__() - 请求前")
        response = self.get_response(request)
        print("OrderB.__call__() - 响应后")
        return response

# 如果MIDDLEWARE = ['OrderA', 'OrderB']
# 输出顺序:
# OrderA.__init__()
# OrderB.__init__()
# OrderA.__call__() - 请求前
# OrderB.__call__() - 请求前
# view()
# OrderB.__call__() - 响应后
# OrderA.__call__() - 响应后

中间件顺序最佳实践

# 推荐的中间件顺序
MIDDLEWARE = [
    # 安全中间件(最先执行)
    'django.middleware.security.SecurityMiddleware',
    
    # 会话中间件(需要在认证前)
    'django.contrib.sessions.middleware.SessionMiddleware',
    
    # 公共中间件
    'django.middleware.common.CommonMiddleware',
    
    # CSRF保护(在认证后)
    'django.middleware.csrf.CsrfViewMiddleware',
    
    # 认证中间件
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    
    # 消息中间件
    'django.contrib.messages.middleware.MessageMiddleware',
    
    # 静态文件中间件
    'django.middleware.staticfiles.StaticFilesMiddleware',
    
    # 点击劫持防护
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    
    # 自定义中间件(最后执行)
    'myapp.middleware.LoggingMiddleware',
    'myapp.middleware.PerformanceMonitoringMiddleware',
]

常见中间件应用场景

认证中间件

# myapp/middleware/auth_middleware.py
import jwt
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.utils.deprecation import MiddlewareMixin
from myapp.models import CustomUser

class JWTAuthMiddleware(MiddlewareMixin):
    """JWT认证中间件"""
    
    def process_request(self, request):
        """处理JWT认证"""
        auth_header = request.META.get('HTTP_AUTHORIZATION')
        
        if auth_header and auth_header.startswith('Bearer '):
            token = auth_header.split(' ')[1]
            
            try:
                # 解码JWT令牌
                payload = jwt.decode(
                    token, 
                    settings.SECRET_KEY, 
                    algorithms=['HS256']
                )
                
                # 获取用户
                user_id = payload.get('user_id')
                user = CustomUser.objects.get(id=user_id)
                
                # 设置请求用户
                request.user = user
                
            except jwt.ExpiredSignatureError:
                request.user = AnonymousUser()
            except jwt.InvalidTokenError:
                request.user = AnonymousUser()
            except CustomUser.DoesNotExist:
                request.user = AnonymousUser()
        else:
            # 如果没有令牌,使用默认认证
            pass
        
        return None

限流中间件

# myapp/middleware/rate_limit_middleware.py
import time
from collections import defaultdict
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin

class RateLimitMiddleware(MiddlewareMixin):
    """限流中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response
        self.requests = defaultdict(list)  # 存储请求时间
        self.limit = 10  # 每分钟最大请求数
        self.window = 60  # 时间窗口(秒)
    
    def __call__(self, request):
        client_ip = self.get_client_ip(request)
        
        # 清理过期的请求记录
        current_time = time.time()
        self.requests[client_ip] = [
            req_time for req_time in self.requests[client_ip]
            if current_time - req_time < self.window
        ]
        
        # 检查是否超过限制
        if len(self.requests[client_ip]) >= self.limit:
            return HttpResponse(
                "Too Many Requests", 
                status=429,
                headers={'Retry-After': str(self.window)}
            )
        
        # 记录当前请求
        self.requests[client_ip].append(current_time)
        
        response = self.get_response(request)
        return response
    
    def get_client_ip(self, request):
        """获取客户端IP"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip

多语言中间件

# myapp/middleware/language_middleware.py
from django.utils.deprecation import MiddlewareMixin
from django.utils import translation
from django.conf import settings
from django.http import HttpResponse

class LanguageMiddleware(MiddlewareMixin):
    """多语言中间件"""
    
    def process_request(self, request):
        """处理语言设置"""
        # 从URL参数获取语言
        lang_code = request.GET.get('lang')
        
        # 或从请求头获取
        if not lang_code:
            accept_language = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
            if accept_language:
                lang_code = accept_language.split(',')[0].split('-')[0]
        
        # 或从会话获取
        if not lang_code and hasattr(request, 'session'):
            lang_code = request.session.get('language')
        
        # 或从用户偏好获取
        if not lang_code and request.user.is_authenticated:
            lang_code = getattr(request.user, 'language', 'en')
        
        # 验证语言代码
        if lang_code and lang_code in dict(settings.LANGUAGES).keys():
            translation.activate(lang_code)
            request.LANGUAGE_CODE = translation.get_language()
            
            # 保存到会话
            if hasattr(request, 'session'):
                request.session['language'] = lang_code
        else:
            # 使用默认语言
            translation.activate(settings.LANGUAGE_CODE)
            request.LANGUAGE_CODE = settings.LANGUAGE_CODE
        
        return None
    
    def process_response(self, request, response):
        """设置语言Cookie"""
        if hasattr(request, 'LANGUAGE_CODE'):
            response.set_cookie(
                settings.LANGUAGE_COOKIE_NAME,
                request.LANGUAGE_CODE,
                max_age=settings.LANGUAGE_COOKIE_AGE,
                path=settings.LANGUAGE_COOKIE_PATH,
                domain=settings.LANGUAGE_COOKIE_DOMAIN,
            )
        return response

中间件最佳实践

中间件开发准则

# 中间件开发最佳实践
class BestPracticeMiddleware:
    """中间件最佳实践示例"""
    
    def __init__(self, get_response):
        self.get_response = get_response
        # 1. 在__init__中进行初始化,避免重复创建资源
        self.setup_resources()
    
    def __call__(self, request):
        # 2. 快速执行,避免阻塞
        # 3. 处理异常,不影响其他中间件
        try:
            # 4. 在请求前的处理
            self.pre_process(request)
            
            # 调用下一个中间件或视图
            response = self.get_response(request)
            
            # 5. 在响应后的处理
            self.post_process(request, response)
            
            return response
        except Exception as e:
            # 6. 记录错误但不中断流程
            self.handle_error(request, e)
            raise  # 或者返回错误响应
    
    def pre_process(self, request):
        """请求前处理"""
        # 只进行必要的处理
        pass
    
    def post_process(self, request, response):
        """响应后处理"""
        # 只进行必要的处理
        pass
    
    def handle_error(self, request, exception):
        """错误处理"""
        # 记录错误但不影响正常流程
        import logging
        logger = logging.getLogger(__name__)
        logger.error(f"Middleware error: {exception}", exc_info=True)
    
    def setup_resources(self):
        """初始化资源"""
        # 在这里初始化需要的资源
        pass

性能优化

# 中间件性能优化
class OptimizedMiddleware:
    """性能优化的中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response
        # 1. 避免在__init__中进行耗时操作
        self.compiled_regex = None  # 延迟编译
    
    def __call__(self, request):
        # 2. 使用缓存避免重复计算
        if not self.compiled_regex:
            import re
            self.compiled_regex = re.compile(r'^/api/')
        
        # 3. 快速路径:尽早返回
        if not self.compiled_regex.match(request.path):
            return self.get_response(request)
        
        # 4. 只在必要时执行处理逻辑
        response = self.get_response(request)
        self.process_api_response(request, response)
        
        return response
    
    def process_api_response(self, request, response):
        """只处理API响应"""
        # 处理逻辑
        pass

错误处理

# 中间件错误处理
class SafeMiddleware:
    """安全的错误处理中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        try:
            response = self.get_response(request)
            return response
        except Exception as e:
            # 记录错误
            import logging
            logger = logging.getLogger(__name__)
            logger.error(f"Error in middleware chain: {e}", exc_info=True)
            
            # 返回友好的错误页面或让后续处理
            raise
    
    def process_exception(self, request, exception):
        """处理异常"""
        # 可以返回自定义错误响应
        from django.http import JsonResponse
        if request.path.startswith('/api/'):
            return JsonResponse({
                'error': 'Internal Server Error',
                'message': str(exception)
            }, status=500)
        return None

常见问题与解决方案

问题1:中间件不执行

症状:定义的中间件没有生效

解决方案

# 1. 检查中间件是否在MIDDLEWARE设置中
# settings.py
MIDDLEWARE = [
    # ... 其他中间件
    'myapp.middleware.MyMiddleware',  # 确保路径正确
]

# 2. 检查中间件类的定义是否正确
class MyMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        print("中间件执行了")  # 添加调试输出
        response = self.get_response(request)
        return response

# 3. 检查是否有语法错误
# 确保中间件文件可以被正确导入

问题2:中间件顺序问题

症状:中间件功能异常,如认证失败

解决方案

# 正确的中间件顺序
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',  # 会话必须在认证前
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',  # CSRF在认证后
    'django.contrib.auth.middleware.AuthenticationMiddleware',  # 认证中间件
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'myapp.middleware.CustomMiddleware',  # 自定义中间件
]

# 错误示例:认证中间件在会话中间件之前
MIDDLEWARE = [
    'django.contrib.auth.middleware.AuthenticationMiddleware',  # 错误顺序
    'django.contrib.sessions.middleware.SessionMiddleware',   # 会话中间件后
    # ...
]

问题3:中间件性能问题

症状:页面加载缓慢

解决方案

# 优化前:每次都执行耗时操作
class SlowMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # 每次都执行数据库查询 - 性能差
        expensive_operation = MyModel.objects.all()  # 避免这样做
        response = self.get_response(request)
        return response

# 优化后:只在需要时执行
class FastMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # 初始化时执行一次
        self.expensive_data = self.load_expensive_data()
    
    def __call__(self, request):
        # 只在特定条件下执行处理
        if self.should_process(request):
            self.process_request(request)
        
        response = self.get_response(request)
        return response
    
    def should_process(self, request):
        """判断是否需要处理此请求"""
        return request.path.startswith('/api/')
    
    def load_expensive_data(self):
        """加载耗时数据"""
        return MyModel.objects.all()

# 使用缓存
from django.core.cache import cache

class CachedMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def get_config(self):
        """获取配置,使用缓存"""
        config = cache.get('middleware_config')
        if config is None:
            config = self.load_config_from_db()
            cache.set('middleware_config', config, 300)  # 缓存5分钟
        return config

问题4:中间件中的异常处理

症状:中间件异常导致整个应用崩溃

解决方案

# 安全的异常处理
class SafeMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.logger = logging.getLogger(__name__)
    
    def __call__(self, request):
        try:
            # 预处理
            self.pre_process(request)
            
            response = self.get_response(request)
            
            # 后处理
            self.post_process(request, response)
            
            return response
        except Exception as e:
            # 记录错误但不影响请求处理
            self.logger.error(f"Middleware error: {e}", exc_info=True)
            
            # 返回原始响应而不中断流程
            return self.get_response(request)
    
    def pre_process(self, request):
        try:
            # 可能出错的预处理逻辑
            user_agent = request.META.get('HTTP_USER_AGENT', '')
            if 'malicious' in user_agent.lower():
                # 返回阻止响应
                return HttpResponse("Access Denied", status=403)
        except Exception as e:
            self.logger.warning(f"Pre-process error: {e}")
            return None  # 继续处理请求
    
    def post_process(self, request, response):
        try:
            # 可能出错的后处理逻辑
            if request.user.is_authenticated:
                # 记录用户活动
                pass
        except Exception as e:
            self.logger.warning(f"Post-process error: {e}")

本章小结

在本章中,我们深入学习了Django中间件系统:

  1. 中间件概念:理解了中间件作为请求/响应处理钩子的作用
  2. 中间件架构:掌握了中间件的执行流程和方法调用顺序
  3. 内置中间件:学习了Django提供的各种内置中间件及其配置
  4. 自定义中间件:掌握了创建各种功能中间件的方法
  5. 执行顺序:理解了中间件顺序的重要性及最佳实践
  6. 应用场景:了解了认证、限流、CORS等常见应用场景
  7. 最佳实践:学习了性能优化和错误处理的最佳实践

核心要点回顾

"""
本章核心要点:

1. 中间件是Django请求/响应处理的钩子系统
2. 中间件按顺序执行:请求阶段从前到后,响应阶段从后到前
3. 常用中间件包括安全、会话、CSRF、认证等
4. 自定义中间件需要实现__init__和__call__方法
5. 中间件顺序很重要,会影响功能正常工作
6. 注意中间件的性能影响,避免阻塞操作
"""

下一步学习

现在您已经掌握了Django中间件系统,可以继续学习:

💡 核心要点:中间件是Django框架的重要组成部分,正确使用中间件可以让您在不修改视图的情况下添加全局功能,但要注意性能影响和错误处理。

SEO优化策略

  1. 关键词布局: 在标题、内容中合理布局"Django中间件", "请求处理", "拦截器", "自定义中间件", "Django安全"等关键词
  2. 内容结构: 使用清晰的标题层级(H1-H3),便于搜索引擎理解内容结构
  3. 内部链接: 建立与其他相关教程的内部链接,提升页面权重
  4. 元数据优化: 在页面头部包含描述性的标题、描述和标签

🔗 相关教程推荐

🏷️ 标签云: Django中间件 请求处理 拦截器 自定义中间件 Django安全 性能优化 CORS 认证 限流