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吧.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。