in间件overview
in间件 is DjangoprocessingHTTPrequest and response hookframework. 它 is a 轻量级, low 级别 插件system, 用于全局改变Django 输入 or 输出.
in间件 in Djangorequest/responseprocessing过程in 位置:
- 当user发送HTTPrequest to Djangoapplication时, request首先经过所 has in间件
process_requestmethod (按照settings.pyinMIDDLEWARElist 顺序) . - 然 after request to 达URLrouting, 被分发 to 相应 视graphfunction.
- 视graphfunctionprocessingrequest并返回HTTPresponse.
- response经过所 has in间件
process_responsemethod (按照settings.pyinMIDDLEWARElist 逆序) . - 最 after response被发送回user 浏览器.
提示
in间件可以用于implementation many 种functions, such as身份verification, log记录, cache, 跨域resource共享 (CORS) etc..
in间件 class型
Djangoin间件可以分 for 以 under 几class:
- in 置in间件: Djangoproviding 预定义in间件, such as身份verificationin间件, sessionin间件etc..
- 自定义in间件: Development者根据需要creation in间件.
- 第三方in间件: 由第三方Development者 or 组织providing in间件, such asDjango CORS Headers, Django Debug Toolbaretc..
in 置in间件
Djangoproviding了 many 种 in 置in间件, 用于processingcommon HTTPrequest and response. 以 under is 一些常用 in 置in间件:
SecurityMiddleware
providing了 many 种security增强functions, such as:
- 设置
X-XSS-Protection,X-Content-Type-Optionsetc.security头. - 强制HTTPS重定向.
- 防止点击劫持攻击.
SessionMiddleware
managementusersession, providing了 in request之间storeuserdata mechanism.
CommonMiddleware
processingcommon HTTPfunctions, such as:
- URL规范化 (添加/delete尾部斜杠) .
- processing
If-Modified-Since头. - 设置
Content-Length头.
CsrfViewMiddleware
providing跨站request伪造 (CSRF) 保护, 防止恶意网站伪造userrequest.
AuthenticationMiddleware
将Userobject添加 to requestin, 方便 in 视graphin访问当 before loginuser.
MessageMiddleware
managementusermessage, 允许 in request之间store and retrieveusermessage.
XFrameOptionsMiddleware
防止点击劫持攻击, through设置X-Frame-Options头控制页面 is 否可以 in iframein显示.
自定义in间件
除了using in 置in间件 out , 还可以creation自定义in间件来implementationspecific functions.
in间件 creationmethod
in Django 1.10及以 on versionin, creationin间件 has 两种method:
- 基于function in间件: usingfunction定义in间件, 接收
get_responseparameter andrequestparameter. - 基于class in间件: usingclass定义in间件, implementation
__init__and__call__method.
基于function in间件
# blog/middleware.py
from django.shortcuts import redirect
# 基于function in间件
def simple_middleware(get_response):
# 一次性初始化code
print("Simple middleware initialized")
def middleware(request):
# request to 达视graph之 before 执行 code
print(f"Request: {request.method} {request.path}")
# 调用视graphfunction, 获取response
response = get_response(request)
# 视graph返回response之 after 执行 code
print(f"Response: {response.status_code}")
return response
return middleware
基于class in间件
# blog/middleware.py
class SimpleMiddleware:
def __init__(self, get_response):
# 一次性初始化code
self.get_response = get_response
print("Class-based middleware initialized")
def __call__(self, request):
# request to 达视graph之 before 执行 code
print(f"Request: {request.method} {request.path}")
# 调用视graphfunction, 获取response
response = self.get_response(request)
# 视graph返回response之 after 执行 code
print(f"Response: {response.status_code}")
return response
in间件 othermethod
基于class in间件还可以implementation以 under method, 用于processingspecific HTTPrequest and response阶段:
- process_view(request, view_func, view_args, view_kwargs): in Django调用视graphfunction之 before 执行.
- process_exception(request, exception): 当视graphfunction抛出exception时执行.
- process_template_response(request, response): 当视graphfunction返回
TemplateResponseor etc.价object时执行.
process_viewmethod
# blog/middleware.py
class ViewMiddleware:
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):
# in 调用视graphfunction之 before 执行
print(f"Calling view: {view_func.__name__} with args: {view_args}, kwargs: {view_kwargs}")
# 可以返回HttpResponseobject, 提 before 结束request/response周期
# return HttpResponse("Processed by process_view")
process_exceptionmethod
# blog/middleware.py
class ExceptionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_exception(self, request, exception):
# 当视graphfunction抛出exception时执行
print(f"Exception occurred: {exception}")
# 可以返回HttpResponseobject, processingexception
# return HttpResponse(f"Error: {exception}", status=500)
process_template_responsemethod
# blog/middleware.py
class TemplateResponseMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_template_response(self, request, response):
# 当视graphfunction返回TemplateResponse时执行
print(f"Processing template response: {response.template_name}")
# 可以modifyresponseobject
response.context_data['middleware_data'] = 'Added by middleware'
return response
registerin间件
creationin间件 after , 需要 in settings.pyinregister:
# settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# register自定义in间件
'blog.middleware.SimpleMiddleware',
'blog.middleware.ViewMiddleware',
'blog.middleware.ExceptionMiddleware',
'blog.middleware.TemplateResponseMiddleware',
]
in间件 执行顺序
in间件 执行顺序非常 important , 它决定了in间件processingrequest and response 顺序.
request阶段 执行顺序
当user发送HTTPrequest时, request按照settings.pyinMIDDLEWARElist 顺序依次经过每个in间件 process_request or __call__method (request to 达视graph之 before 部分) .
response阶段 执行顺序
当视graphfunction返回response时, response按照settings.pyinMIDDLEWARElist 逆序依次经过每个in间件 process_response or __call__method (视graph返回response之 after 部分) .
process_view, process_exception and process_template_response 执行顺序
process_view: 按照MIDDLEWARElist 顺序执行.process_exception: 按照MIDDLEWARElist 逆序执行, 只 has 当视graphfunction抛出exception时才会执行.process_template_response: 按照MIDDLEWARElist 逆序执行, 只 has 当视graphfunction返回TemplateResponse时才会执行.
warning
in间件 执行顺序会影响application behavior, 因此 in registerin间件时需要仔细考虑顺序. 例such as, 身份verificationin间件应该 in 需要访问userinformation in间件之 before register.
in间件 application场景
in间件可以用于implementation many 种functions, 以 under is 一些common application场景:
身份verification and authorization
可以usingin间件来verificationuser身份, 控制user for specificURL 访问permission.
# blog/middleware.py
from django.shortcuts import redirect
class AuthMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 不需要身份verification URL
exempt_urls = ['/login/', '/register/', '/admin/']
# checkuser is 否已login
if not request.user.is_authenticated and request.path not in exempt_urls:
return redirect('/login/')
response = self.get_response(request)
return response
log记录
可以usingin间件来记录所 has HTTPrequest and response 详细information, 便于debug and monitor.
# blog/middleware.py
import logging
from datetime import datetime
logger = logging.getLogger(__name__)
class LoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 记录requestinformation
start_time = datetime.now()
logger.info(f"Request: {request.method} {request.path} {request.META.get('REMOTE_ADDR')}")
# 调用视graphfunction
response = self.get_response(request)
# 记录responseinformation
duration = datetime.now() - start_time
logger.info(f"Response: {response.status_code} {duration.total_seconds()}s")
return response
cache
可以usingin间件来cacheHTTPresponse, improvingapplication performance.
# blog/middleware.py
from django.core.cache import cache
from django.http import HttpResponse
class CacheMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 只cacheGETrequest
if request.method == 'GET':
# 生成cache键
cache_key = f"page:{request.path}"
# 尝试 from cachein获取response
cached_response = cache.get(cache_key)
if cached_response:
return HttpResponse(cached_response)
# 调用视graphfunction
response = self.get_response(request)
# cacheGETrequest response
if request.method == 'GET' and response.status_code == 200:
cache.set(cache_key, response.content, 60 * 15) # cache15分钟
return response
跨域resource共享 (CORS)
可以usingin间件来implementation跨域resource共享, 允许不同域 before 端application访问Django API.
# blog/middleware.py
class CORSMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
# 设置CORS头
response['Access-Control-Allow-Origin'] = '*' # 允许所 has 域访问
response['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
response['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
response['Access-Control-Max-Age'] = '86400' # 预检request cache时间, 单位秒
return response
in间件 best practices
- 保持in间件简洁: in间件应该只processing单一functions, 避免 in 一个in间件inimplementation many 个不相关 functions.
- 考虑performance影响: in间件会 in 每个HTTPrequest and responsein执行, 因此应该尽量reducingin间件 数量 and complexity, 避免影响application performance.
- 注意执行顺序: in间件 执行顺序非常 important , 应该根据in间件 functions and 依赖relationships合理安排顺序.
- using in 置in间件: 优先usingDjangoproviding in 置in间件, 它们经过了充分 test and optimization.
- testin间件: writingtest用例来verificationin间件 functions and performance.
练习 1: creationlog记录in间件
- creation一个基于class in间件, 用于记录所 has HTTPrequest and response 详细information.
- 记录 informationincluding: requestmethod, URL, 客户端IP地址, responsestatus码, requestprocessing时间etc..
- 将loginformation写入file or datalibrary.
- in settings.pyinregisterin间件.
- testin间件 functions.
练习 2: creation身份verificationin间件
- creation一个基于function in间件, 用于verificationuser身份.
- for 于未login user, 将其重定向 to login页面.
- 允许某些URL (such aslogin页, register页) 不for身份verification.
- in settings.pyinregisterin间件.
- testin间件 functions.
练习 3: creationCORSin间件
- creation一个基于class in间件, 用于implementation跨域resource共享.
- 允许所 has 域访问API.
- 允许common HTTPmethod (GET, POST, PUT, DELETE, OPTIONS) .
- 允许common HTTP头 (Content-Type, Authorization) .
- in settings.pyinregisterin间件.
- testin间件 functions.