在详细介绍Django处理http请求的各个关键的流程点之前,笔者先简要的提及一下整个流程让各位同学有一个总体的认识。
- 在接受一个Http请求之前的准备
- 启动一个支持WSGI网关协议的服务器监听端口等待外界的Http请求,比如Django自带的开发者服务器或者uWSGI服务器。
- 服务器根据WSGI协议指定相应的Handler来处理Http请求,并且初始化该Handler,在Django框架中由框架自身负责实现这一个Handler。
- 此时服务器已处于监听状态,可以接受外界的Http请求
- 当一个http请求到达服务器的时候
- 服务器根据WSGI协议从Http请求中提取出必要的参数组成一个字典(environ)并传入Handler中进行处理。
- 在Handler中对已经符合WSGI协议标准规定的http请求进行分析,比如加载Django提供的中间件,路由分配,调用路由匹配的视图等。
- 返回一个可以被浏览器解析的符合Http协议的HttpResponse。
在本文中,笔者将会在源码中标出一些自己的理解,并且只会贴出需要用到的源码(比如一个类可能不会贴出所有的方法)。
WSGIServer and WSGIHandler
如果各位同学对WSGI协议没有什么了解的话,可以先参考一下笔者之前写的这篇博客:WSGI初探及wsgiref简单实现。
在启动支持WSGI协议的服务器的时候,可以看为是一个WSGIServer的类的实例化,而它在初始化的过程中指定了WSGIHandler,而这一个Handler其实就是笔者在上面的博客中提及的应用程序部分。
以Django内置的WSGIServer为例,在初始化的时候它就持有Handler的路径,即Django项目中settings.py的WSGI_APPLICATION属性,该属性指向与settings.py在同一目录下的wsgi.py中的application变量。
下面是官方文档的解释:
WSGI servers obtain the path to the application callable from their configuration. Django’s built-in server, namely the runserver command, reads it from the WSGI_APPLICATION setting. By default, it’s set to <project_name>.wsgi.application, which points to the application callable in <project_name>/wsgi.py.
在默认项目的wsgi.py文件中,application是由一个get_wsgi_application的函数返回的。
def get_wsgi_application():
"""
The public interface to Django's WSGI support. Should return a WSGI
callable.
Allows us to avoid making django.core.handlers.WSGIHandler public API, in
case the internal WSGI implementation changes or moves in the future.
"""
django.setup(set_prefix=False)
return WSGIHandler()
初始化WSGIHandler
# django.core.handlers.wsgi.py
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def __init__(self, *args, **kwargs):
super(WSGIHandler, self).__init__(*args, **kwargs)
# 调用了继承自BaseHandler的load_middleware方法
self.load_middleware()
# django.core.handlers.base.py
class BaseHandler(object):
def __init__(self):
self._request_middleware = None
self._view_middleware = None
self._template_response_middleware = None
self._response_middleware = None
self._exception_middleware = None
self._middleware_chain = None
def load_middleware(self):
"""
Populate middleware lists from settings.MIDDLEWARE (or the deprecated
MIDDLEWARE_CLASSES).
Must be called after the environment is fixed (see __call__ in subclasses).
"""
# 定义了Django中一系列的钩子,比如process_request, process_view, process_response等钩子,这些钩子可应用于对请求进行预处理或者对响应进行处理
self._request_middleware = []
self._view_middleware = []
self._template_response_middleware = []
self._response_middleware = []
self._exception_middleware = []
# 笔者使用的是1.9版本的Django,因此在settings定义的仍然是MIDDLEWARE_CLASSES,因此进入第一个if选项
if settings.MIDDLEWARE is None:
warnings.warn(