Django应用程序入口WSGIHandler源码解析
作者:捣乱小子 发布时间:2021-07-09 04:33:22
前言
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 中能找到如下设置:
# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'tomato.wsgi.application'
如你所见, WSGI_APPLICATION 就指定了应用程序. 而按图索骥下去, 找到项目中的 wsgi.py, 已经除去了所有的注释:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tomato.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
因此, WSGI_APPLICATION 所指定的即为 wsgi.py 中的全局变量 application. 故伎重演, 继续找下去. 在 django.core 模块中的 wsgi.py 中找到 get_wsgi_application() 函数的实现:
from django.core.handlers.wsgi import WSGIHandler
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.
"""
"""
# 继承, 但只实现了 __call__ 方法, 方便使用
class WSGIHandler(base.BaseHandler):
"""
return WSGIHandler()
在 get_wsgi_application() 中实例化了 WSGIHandler, 并无其他操作.
WSGIHandler
紧接着在 django.core.handler 的 base.py 中找到 WSGIHandler 的实现.
# 继承, 但只实现了 __call__ 方法, 方便使用
class WSGIHandler(base.BaseHandler):
initLock = Lock()
# 关于此, 日后展开, 可以将其视为一个代表 http 请求的类
request_class = WSGIRequest
# WSGIHandler 也可以作为函数来调用
def __call__(self, environ, start_response):
# Set up middleware if needed. We couldn't do this earlier, because
# settings weren't available.
# 这里的检测: 因为 self._request_middleware 是最后才设定的, 所以如果为空,
# 很可能是因为 self.load_middleware() 没有调用成功.
if self._request_middleware is None:
with self.initLock:
try:
# Check that middleware is still uninitialised.
if self._request_middleware is None:
因为 load_middleware() 可能没有调用, 调用一次.
self.load_middleware()
except:
# Unload whatever middleware we got
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)
except UnicodeDecodeError:
logger.warning('Bad Request (UnicodeDecodeError)',
exc_info=sys.exc_info(),
extra={
'status_code': 400,
}
)
response = http.HttpResponseBadRequest()
else:
# 调用 self.get_response(), 将会返回一个相应对象 response<br> ############# 关键的操作, self.response() 可以获取响应数据.
response = self.get_response(request)
# 将 self 挂钩到 response 对象
response._handler_class = self.__class__
try:
status_text = STATUS_CODE_TEXT[response.status_code]
except KeyError:
status_text = 'UNKNOWN STATUS CODE'
# 状态码
status = '%s %s' % (response.status_code, status_text)
response_headers = [(str(k), str(v)) for k, v in response.items()]
# 对于每个一个 cookie, 都在 header 中设置: Set-cookie xxx=yyy
for c in response.cookies.values():
response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
# start_response() 操作已经在上节中介绍了
start_response(force_str(status), response_headers)
# 成功返回相应对象
return response
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 中可以找到: class BaseHandler(object):...
这一节服务器部分已经结束, 接下来的便是中间件和应用程序了, 相关内容会在下节的 BaseHandler 中展开. 我已经在 github 备份了 Django 源码的注释: Decode-Django, 有兴趣的童鞋 fork 吧.
来源:https://www.cnblogs.com/daoluanxiaozi/p/3315838.html


猜你喜欢
- Django自带有个强大的后天管理系统,接下来我就给大家介绍一下x的admin一些强大的操作及后台美化。首先给大家介绍一些xadmin的注册
- 大家都知道Vue.js是中国人创造出来的,简单易用,所以必须要支持一下Vue采用的MVVM设计模式也就是说model和view绑定 mode
- 前言2048游戏规则:简单的移动方向键让数字叠加,并且获得这些数字每次叠加后的得分,当出现2048这个数字时游戏胜利。同时每次移动方向键时,
- 概述:本控件使用 html+css+javascript模拟HTML内置的select元素,实现其部分方法与属性,也增加了一部分功能,并且从
- 一、逻辑数据库和表的设计数据库的逻辑设计、包括表与表之间的关系是优化关系型数据库性能的核心。一个好的逻辑数据库设计可以为优化数据库和应用程序
- 前言我们的游戏资源处理工具是Python实现的,功能包括csv解析,UI材质处理,动画资源解析、批处理,Androd&iOS自动打包
- 一,开篇分析Hi,大家!今天这系列文章主要是说说如何开发基于“JavaScript”的插件式开发,我想很多人对”插件“这个词并不陌生,有的人
- 一般上电子商务网站买东西的用户分三种:随便看看,就是不买先看看,买不买再说就是来买东西的这样的需求反应到产品页的购买按钮上,我们一般会看到购
- 流式布局流式布局,也叫做瀑布流布局,是网页中经常使用的一种页面布局方式,它的原理就是将高度固定,然后图片的宽度自适应,这样加载出来的图片看起
- 如下所示:import urllib.requestimport sysimport http.cookiejarimport urllib
- 前言:opencv最主要的的功能是用于图像处理,所以图像的概念贯穿了整个opencv,与其相关的核心类就是Mat。像素:图片尺寸以像素为单位
- 本文实例讲述了Python双链表原理与实现方法。分享给大家供大家参考,具体如下:Python实现双链表文章目录Python实现双链表定义链表
- Python项目中很多时候会需要将时间在Datetime格式和TimeStamp格式之间转化,又或者你需要将UTC时间转化为本地时间,本文总
- 1、目前来看,百付宝仅仅只是C2C的一个支付后台。他的内容只集中于“钱和订单”两个环节,没有其他干扰信息。2、百付宝的界面表现很简单。因为简
- <pre name="code" class="python">creazy.txt文件
- 最近,帮同事重写了一个MySQL SQL语句,该SQL语句涉及两张表,其中一张表是字典表(需返回一个字段),另一张表是业务表(本身就有150
- 本文实例讲述了Python批量重命名同一文件夹下文件的方法。分享给大家供大家参考。具体分析如下:朋友发了一个文件夹过来,里面的图片都以 .t
- eclare @str nvarchar(50);set @str='462,464,2';select @str as &
- 1.main.js文件中添加已下代码Vue.directive('drag', { //1.指令绑定到元素上回立
- 为什么会有多个分支一般项目在开发阶段,都会创建多个分支,用于不同开发阶段的版本发布如:master、dev等,之所以会有这种多分支情况,就是