Django应用程序入口WSGIHandler源码解析
前言
WSGI有三个部分,分别为服务器(server),应用程序(application)和中间件(middleware).已经知道,服务器方面会调用应用程序来处理请求,在应用程序中有真正的处理逻辑,在这里面几乎可以做任何事情,其中的中间件就会在里面展开.
Django中的应用程序
任何的WSGI应用程序,都必须是一个start_response(status,response_headers,exc_info=None)形式的函数或者定义了__call__的类.而django.core.handlers就用后一种方式实现了应用程序:WSGIHandler.在这之前,Django是如何指定自己的application的,在一个具体的Django项目中,它的方式如下:
在mysite.settings.py中能找到如下设置:
#PythondottedpathtotheWSGIapplicationusedbyDjango'srunserver. WSGI_APPLICATION='tomato.wsgi.application'
如你所见,WSGI_APPLICATION就指定了应用程序.而按图索骥下去,找到项目中的wsgi.py,已经除去了所有的注释:
importos
os.environ.setdefault("DJANGO_SETTINGS_MODULE","tomato.settings")
fromdjango.core.wsgiimportget_wsgi_application
application=get_wsgi_application()
因此,WSGI_APPLICATION所指定的即为wsgi.py中的全局变量application.故伎重演,继续找下去.在django.core模块中的wsgi.py中找到get_wsgi_application()函数的实现:
fromdjango.core.handlers.wsgiimportWSGIHandler defget_wsgi_application(): """ ThepublicinterfacetoDjango'sWSGIsupport.ShouldreturnaWSGI callable. Allowsustoavoidmakingdjango.core.handlers.WSGIHandlerpublicAPI,in casetheinternalWSGIimplementationchangesormovesinthefuture. """ """ #继承,但只实现了__call__方法,方便使用 classWSGIHandler(base.BaseHandler): """ returnWSGIHandler()
在get_wsgi_application()中实例化了WSGIHandler,并无其他操作.
WSGIHandler
紧接着在django.core.handler的base.py中找到WSGIHandler的实现.
#继承,但只实现了__call__方法,方便使用
classWSGIHandler(base.BaseHandler):
initLock=Lock()
#关于此,日后展开,可以将其视为一个代表http请求的类
request_class=WSGIRequest
#WSGIHandler也可以作为函数来调用
def__call__(self,environ,start_response):
#Setupmiddlewareifneeded.Wecouldn'tdothisearlier,because
#settingsweren'tavailable.
#这里的检测:因为self._request_middleware是最后才设定的,所以如果为空,
#很可能是因为self.load_middleware()没有调用成功.
ifself._request_middlewareisNone:
withself.initLock:
try:
#Checkthatmiddlewareisstilluninitialised.
ifself._request_middlewareisNone:
因为load_middleware()可能没有调用,调用一次.
self.load_middleware()
except:
#Unloadwhatevermiddlewarewegot
self._request_middleware=None
raise
set_script_prefix(base.get_script_name(environ))
signls.request_started.send(sender=self.__class__)#__class__代表自己的类
try:
#实例化request_class=WSGIRequest,将在日后文章中展开,可以将其视为一个代表http请求的类
request=self.request_class(environ)
exceptUnicodeDecodeError:
logger.warning('BadRequest(UnicodeDecodeError)',
exc_info=sys.exc_info(),
extra={
'status_code':400,
}
)
response=http.HttpResponseBadRequest()
else:
#调用self.get_response(),将会返回一个相应对象response
#############关键的操作,self.response()可以获取响应数据.
response=self.get_response(request)
#将self挂钩到response对象
response._handler_class=self.__class__
try:
status_text=STATUS_CODE_TEXT[response.status_code]
exceptKeyError:
status_text='UNKNOWNSTATUSCODE'
#状态码
status='%s%s'%(response.status_code,status_text)
response_headers=[(str(k),str(v))fork,vinresponse.items()]
#对于每个一个cookie,都在header中设置:Set-cookiexxx=yyy
forcinresponse.cookies.values():
response_headers.append((str('Set-Cookie'),str(c.output(header=''))))
#start_response()操作已经在上节中介绍了
start_response(force_str(status),response_headers)
#成功返回相应对象
returnresponse
WSGIHandler类只实现了def__call__(self,environ,start_response),使它本身能够成为WSGI中的应用程序,并且实现__call__能让类的行为跟函数一样,详见python__call__方法.
def__call__(self,environ,start_response)方法中调用了WSGIHandler.get_response()方法以获取响应数据对象response.从WSGIHandler的实现来看,它并不是最为底层的:WSGIHandler继承自base.BaseHandler,在django.core.handler的base.py中可以找到:classBaseHandler(object):...
这一节服务器部分已经结束,接下来的便是中间件和应用程序了,相关内容会在下节的BaseHandler中展开.我已经在github备份了Django源码的注释:Decode-Django,有兴趣的童鞋fork吧.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。