#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中间件系统:
- 中间件概念:理解了中间件作为请求/响应处理钩子的作用
- 中间件架构:掌握了中间件的执行流程和方法调用顺序
- 内置中间件:学习了Django提供的各种内置中间件及其配置
- 自定义中间件:掌握了创建各种功能中间件的方法
- 执行顺序:理解了中间件顺序的重要性及最佳实践
- 应用场景:了解了认证、限流、CORS等常见应用场景
- 最佳实践:学习了性能优化和错误处理的最佳实践
#核心要点回顾
"""
本章核心要点:
1. 中间件是Django请求/响应处理的钩子系统
2. 中间件按顺序执行:请求阶段从前到后,响应阶段从后到前
3. 常用中间件包括安全、会话、CSRF、认证等
4. 自定义中间件需要实现__init__和__call__方法
5. 中间件顺序很重要,会影响功能正常工作
6. 注意中间件的性能影响,避免阻塞操作
"""#下一步学习
现在您已经掌握了Django中间件系统,可以继续学习:
💡 核心要点:中间件是Django框架的重要组成部分,正确使用中间件可以让您在不修改视图的情况下添加全局功能,但要注意性能影响和错误处理。
#SEO优化策略
- 关键词布局: 在标题、内容中合理布局"Django中间件", "请求处理", "拦截器", "自定义中间件", "Django安全"等关键词
- 内容结构: 使用清晰的标题层级(H1-H3),便于搜索引擎理解内容结构
- 内部链接: 建立与其他相关教程的内部链接,提升页面权重
- 元数据优化: 在页面头部包含描述性的标题、描述和标签
🔗 相关教程推荐
- 视图系统与URL路由 - 请求处理基础
- 信号系统 - 事件驱动编程
- 安全最佳实践 - 应用安全
🏷️ 标签云: Django中间件 请求处理 拦截器 自定义中间件 Django安全 性能优化 CORS 认证 限流

