Django访问过程(一)中我们了解到请求内容进入了django.core.handlers.wsgi.WSGIHandler.__call__进行处理,下面我们接着个方法继续解读源码。
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# django服务启动阶段已经实例化中间件并加载了中间件的相关方法。
self.load_middleware()
def __call__(self, environ, start_response):
# 开辟线程变量
set_script_prefix(get_script_name(environ))
# 发送一个requet处理信号
# 前面我们提到runserver命令模块,命令继承了‘django.core.management.base.BaseCommand’类,
# 而BaseCommand中执行了'from django.db import DEFAULT_DB_ALIAS, connections'导入模块操作,
# 在db.__init__.py中建立了request_started信号连接。
'''
# 建立信号连接,传递reset_queries作为处理信号的方法
signals.request_started.connect(reset_queries)
# 建立信号连接,传递close_old_connections作为处理信号的方法
signals.request_started.connect(close_old_connections)
# 建立信号连接,传递close_old_connections作为处理信号的方法
signals.request_finished.connect(close_old_connections)
'''
signals.request_started.send(sender=self.__class__, environ=environ)
# 用WSGIRequest封装request,这里就是我们视图中用到的request的来源。
request = self.request_class(environ)
# 设置路由
# 将request交给中间件处理
# 这里得到了经过中间件和视图处理过的response
response = self.get_response(request)
# get_response
'''
def get_response(self, request):
"""Return an HttpResponse object for the given HttpRequest."""
# Setup default url resolver for this thread
set_urlconf(settings.ROOT_URLCONF)
# 根据装饰器闭包原理去调用中间件的__call__方法
# 注意中间件的实例化过程是中间件表从下往上
response = self._middleware_chain(request)
response._closable_objects.append(request)
if response.status_code >= 400:
log_response(
'%s: %s', response.reason_phrase, request.path,
response=response,
request=request,
)
return response
'''
# 中间件处理过程如下:
'''
class MiddlewareMixin:
def __init__(self, get_response=None):
# 启动时候load_middleware()对中间件进行实例化,
# 传入了django.core.handlers.base.BaseHandler._get_response
self.get_response = get_response
super().__init__()
def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
# 交给中间件的process_request方法处理,按中间件列表从上到下执行
# 对request进行进一步加工
# 一般情况下没有返回值或者返回响应错误的response
response = self.process_request(request)
# 继续将requets交给django.core.handlers.base.BaseHandler._get_response处理
# 先根据路由配置得到路由表,
# 然后根据请求地址信息从路由表找到视图函数,视图函数的参数
# 接着将requset、视图函数和视图函数参数交给了中间件的process_view处理,按中间件列表从上到下执行
# 如果视图处理过后得到的response有render方法,
# 接着将response交给中间件的process_template_response方法处理,按中间件列表从下往上执行;
# 这里必须得到response结果,否则调用中间件的process_exception方法进行异常处理,按中间件列表从下往上执行。
response = response or self.get_response(request)
if hasattr(self, 'process_response'):
# 将的到的request和response交给中间件的process_response方法处理,按中间件列表从下往上执行
response = self.process_response(request, response)
# 返回处理结果response
return response
'''
# django.core.handlers.base.BaseHandler._get_respons
'''
def _get_response(self, request):
"""
Resolve and call the view, then apply view, exception, and
template_response middleware. This method is everything that happens
inside the request/response middleware.
"""
response = None
if hasattr(request, 'urlconf'):
urlconf = request.urlconf
set_urlconf(urlconf)
resolver = get_resolver(urlconf)
else:
resolver = get_resolver()
# 路由匹配,获取到视图函数和视图函数的参数
resolver_match = resolver.resolve(request.path_info)
callback, callback_args, callback_kwargs = resolver_match
request.resolver_match = resolver_match
# Apply view middleware
# 执行装饰器的process_viewf方法
for middleware_method in self._view_middleware:
response = middleware_method(request, callback, callback_args, callback_kwargs)
if response:
break
if response is None:
wrapped_callback = self.make_view_atomic(callback)
try:
response = wrapped_callback(request, *callback_args, **callback_kwargs)
except Exception as e:
response = self.process_exception_by_middleware(e, request)
# Complain if the view returned None (a common error).
if response is None:
if isinstance(callback, types.FunctionType): # FBV
view_name = callback.__name__
else: # CBV
view_name = callback.__class__.__name__ + '.__call__'
raise ValueError(
"The view %s.%s didn't return an HttpResponse object. It "
"returned None instead." % (callback.__module__, view_name)
)
# If the response supports deferred rendering, apply template
# response middleware and then render the response
# 调用中间件的process_template_response方法,进行模板渲染前处理
elif hasattr(response, 'render') and callable(response.render):
for middleware_method in self._template_response_middleware:
response = middleware_method(request, response)
# Complain if the template response middleware returned None (a common error).
if response is None:
raise ValueError(
"%s.process_template_response didn't return an "
"HttpResponse object. It returned None instead."
% (middleware_method.__self__.__class__.__name__)
)
try:
# 渲染模板
response = response.render()
except Exception as e:
response = self.process_exception_by_middleware(e, request)
return response
'''
response._handler_class = self.__class__
# 响应状态
status = '%d %s' % (response.status_code, response.reason_phrase)
# 响应头封装
response_headers = [
*response.items(),
*(('Set-Cookie', c.output(header='')) for c in response.cookies.values()),
]
# 上一篇我们提到TCPServer以WSGIRequestHandler作为处理请求的接口,
# 在监听到访问请求后该接口将套接字信息封装到ServerHandler,
# 并由ServerHandler的run方法将得到的socket信息和wsgiref.handlers.BaseHandler.start_response传递给WSGIHandler的__call__,
# 该方法进行header处理,status状态码检验
start_response(status, response_headers)
# wsgiref.handlers.BaseHandler.start_response
'''
def start_response(self, status, headers,exc_info=None):
"""'start_response()' callable as specified by PEP 3333"""
if exc_info:
try:
if self.headers_sent:
# Re-raise original exception if headers sent
raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
finally:
exc_info = None # avoid dangling circular ref
elif self.headers is not None:
raise AssertionError("Headers already set!")
self.status = status
self.headers = self.headers_class(headers)
status = self._convert_string_type(status, "Status")
assert len(status)>=4,"Status must be at least 4 characters"
assert status[:3].isdigit(), "Status message must begin w/3-digit code"
assert status[3]==" ", "Status message must have a space after code"
if __debug__:
for name, val in headers:
name = self._convert_string_type(name, "Header name")
val = self._convert_string_type(val, "Header value")
assert not is_hop_by_hop(name),\
f"Hop-by-hop header, '{name}: {val}', not allowed"
return self.write
'''
if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
response = environ['wsgi.file_wrapper'](response.file_to_stream)
# 这里将得到的response返回给django.core.servers.basehttp.ServerHandler.run的self.result,
# 最后交给self.finish_response()将访问结果通过self.wfile返回给请求访问的客户端。
return response
由此可以看到django的访问过程经过如下: