先推荐一个个人认为更好的:http://www.jianshu.com/p/679dee0a4193
django程序在正式环境中往往是通过wsgi程序去启动的,所以运行开始的入口就是django项目的wsgi.py ,这个文件的重点就是调用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()
函数获取一个UWSGIhandler对象,这个UWSGIhandler是一个符合UWSGI协议的对象,这个协议就是自己必须有一个call方法,这个call方法必须要有两个参数,一个environ参数,这个是web服务器传递过来的参数字典,包括环境变量; 还有一个start_response函数去处理http的请求。
这个UWSGIhanler在初始化函数init中去调用load_middleware去装载在settings里面的middleware,其实这些middleware都是一个类,最后会被实例化然后调用,同时这个对象有一个call函数,每来一个url请求,都会去调用UWSGIhandler对象,触发call函数去执行后续流程,这个推测可以在django自身的manage.py runserver分析中可以得到验证,代码如下:
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def __init__(self, *args, **kwargs):
super(WSGIHandler, self).__init__(*args, **kwargs)
self.load_middleware()
def __call__(self, environ, start_response):
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ)
try:
request = self.request_class(environ)
print "request.COOKIES: ", request.COOKIES
print "request.HTTP_AUTHORIZATION: ", request.META.get('HTTP_AUTHORIZATION','No HTTP_AUTHORIZATION')
except UnicodeDecodeError:
logger.warning(
'Bad Request (UnicodeDecodeError)',
exc_info=sys.exc_info(),
extra={
'status_code': 400,
}
)
response = http.HttpResponseBadRequest()
else:
response = self.get_response(request)
response._handler_class = self.__class__
status = '%d %s' % (response.status_code, response.reason_phrase)
response_headers = [(str(k), str(v)) for k, v in response.items()]
for c in response.cookies.values():
response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
start_response(force_str(status), response_headers)
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)
print "type(response), response: ", type(response), response
# print "response.cookies: ", response.items()[0][1]
# print "response.headers: ", response._headers
return response
而最终UWSGI服务器会调去处理UWSGIhandler,下面代码中的application就是UWSGIhandler的实例
class BaseHandler:
def run(self, application):
"""Invoke the application"""
# Note to self: don't move the close()! Asynchronous servers shouldn't
# call close() from finish_response(), so if you close() anywhere but
# the double-error branch here, you'll break asynchronous servers by
# prematurely closing. Async servers must return from 'run()' without
# closing if there might still be output to iterate over.
try:
self.setup_environ()
self.result = application(self.environ, self.start_response)
上面的self.result = application(self.environ, self.start_response)就是调用application实例,从而触发call,这里的application就是
get_uwsgi_application的返回,也就是WSGIhandler的实例对象)。
从WSGIhanler对象中的call中可以看出,首先去构造一个request请求,这个request对象中的信息(主要是在view 函数中用到的信息)都是来自call函数的参数environment,猜测是http客户端传过来的请求信息。初始化好request后,就开始调用get_response()构造要返回的response了。
get_response()中调用了_middleware_chain(request)函数,其实就是调用了_get_response()函数,_get_response函数是处理关键,所以,往下看_get_response函数就好了。
_get_response函数首先做url匹配,即调用resolver.resolve(request.path_info),获得callback,callback其实就是与url匹配的view(视图函数),最后调用视图函数处理request,在_get_response中你可以看到,
for middleware_method in self._view_middleware: #self._view_middleware是在load_middleware函数里面被赋值的。
response = middleware_method(request, callback, callback_args, callback_kwargs)
if response:
break
首先判断middleware_method是否处理了request并返回了response,如果返回了response,那么就不会走到与url匹配的视图函数,也就是下面这段代码:
if response is None: #这里response为 None的情况就是 view_middleware没又返回response对象。
wrapped_callback = self.make_view_atomic(callback) #这一步使视图事务化,因为视图的处理很可能涉及到数据库操作
try:
response = wrapped_callback(request, *callback_args, **callback_kwargs) #真正调用视图函数去处理request请求,也就到了我们自己写的django业务了,即我们自己写的view
except Exception as e:
response = self.process_exception_by_middleware(e, request)
从代码中可以看出,如果response为None,也就是middleware没有返回response,那么就交由我们自己写的view函数去处理。我们自己写的django业务的主要作用是处理我们需要的逻辑,然后将结果封装成一个HttpResponse对象返回。
推荐一个写的更清晰的文章:http://www.jianshu.com/p/679dee0a4193
借用一张图备份: