加载中间件
django服务器在启动和初始化过程中会对settings.py
配置文件中的MIDDLEWARE
列表中配置的中间件进行加载:
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',
]
加载中间件的工作具体由BaseHandler.laod_midddleware
方法实现:
class BaseHandler:
_view_middleware = None
_template_response_middleware = None
_exception_middleware = None
_middleware_chain = None
def load_middleware(self, is_async=False):
"""
Populate middleware lists from settings.MIDDLEWARE.
...
这是服务器启动过程中做的工作,此时还不涉及任何请求的接收和处理。
请求处理
- 请求进来之后,Django将创建线程进行处理,具体构建socket的过程不在此处讨论,总之会把请求封装为
HttpRequest
,此对象包含了一个请求的基本信息,实际处理的时候可能是它的基类WSGIRequest(HttpRequest)
,但这不重要。
class HttpRequest:
"""A basic HTTP request."""
...
def __init__(self):
...
self.GET = QueryDict(mutable=True)
self.POST = QueryDict(mutable=True)
self.COOKIES = {}
self.META = {}
self.FILES = MultiValueDict()
self.path = ""
self.path_info = ""
self.method = None
self.resolver_match = None
self.content_type = None
self.content_params = None
...
- 接下来Django要对请求做下一步的处理,用于处理请求的工具就是上面提到的
BaseHandler
,具体来说可能是它的子类WSGIHandler(base.BaseHandler)
,但这不重要。 - 我们再初始化时就将所有中间件导入进
BaseHandler
中,它将用这些中间件对请求进行处理(想象一条流水线):
class BaseHandler:
...
def get_response(self, request):
...
response = self._middleware_chain(request)
...
深入中间件
我们现在知道,中间件在Django启动时被加载,当一个请求进来的时候中间件会按顺序(想象一条流水线)对请求进行处理,现在我们进入单个中间件中,看看究竟发生了什么。
MiddlewareMixin
是所有中间件的基类,当它被调用的时候,它会去寻找自身的process_request
方法,由process_request
方法对请求对象进行处理。
class MiddlewareMixin:
...
# 此处可以看到中间件在处理请求,具体来说调用了自己的process_request方法
def __call__(self, request):
...
if hasattr(self, "process_request"):
response = self.process_request(request)
...
因此自定义中间件的关键就在于继承MiddlewareMixin
,并重写process_request
方法。以Django自带的SessionMiddleware
为例,它的实现非常简单,就是重写了process_request
方法,实现了取出请求对象中的cookie信息并存储起来的逻辑:
class SessionMiddleware(MiddlewareMixin):
def __init__(self, get_response):
super().__init__(get_response)
engine = import_module(settings.SESSION_ENGINE)
self.SessionStore = engine.SessionStore
def process_request(self, request):
# 取出请求对象并存储
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)
...
中间件还能对视图函数处理完返回的响应对象再做处理,对应的只需要重写process_response
方法,不细致讨论,都是一样的道理,讲这么多就足够了。
总结
因此总结,自定义中间件只需三步:
- 创建自己的中间件类继承
SessionMiddleware
- 想处理请求就重写
process_request
,想处理响应就重写process_response
- 最后需要的中间件注册到
MIDDLEWARE
列表中,注意顺序。