DJango的WSGIHandler和Request的实现

原创
2018/07/03 00:00
阅读数 8

Django里面的WSGI Application

当创建项目的时候, 通常会在我们的项目路径下生成一个wsgi.py文件, 当我们使用gunicorn等工具指定application的时候都会指向这个文件

# wsgi.py
import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "reader.settings")

application = get_wsgi_application()

# core/wsgi
def get_wsgi_application():
django.setup(set_prefix=False)
return WSGIHandler()

我们可以看到最终我们返回的是WSGIHandler这个对象, 按照之前的WSGI接口的学习, 我们可以知道我们的Django框架的业务逻辑都在这个WSGIHandler里面

关于WSGIHandler对象

WSGIHandler的业务逻辑实现如下:

# django/core/handlers/wsgi
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 我们可以看到在生成这个实力的时候, 会调用loading_middleware方法
self.load_middleware()

def __call__(self, environ, start_response):
# 省略脚本和信号的处理
request = self.request_class(environ)
response = self.get_response(request)
response._handler_class = self.__class__
# 拼接返回的头信息,主要包含响应状态、Http头灯信息
status = '%d %s' % (response.status_code, response.reason_phrase)
response_headers = list(response.items())
for c in response.cookies.values():
response_headers.append(('Set-Cookie', c.output(header='')))
start_response(status, response_headers)
# 省略文件处理部分
return response

通过上面的代码可以整理在Django里面的一个请求的处理流程如下

envrioment 请求类 响应类 start_response

middleware后面打算大度

Django中的request

在django里的view开发过程中通常会接收一个request对象, 它究竟是个什么东西?

# django/core/handler/wsgi
class WSGIRequest(HttpRequest):
def __init__(self, environ):
# 通过WSGI服务器传递进来的evn环境信息构建Request对象
self.META = environ
#  获取environment里面的请求方法信息
self.method = environ['REQUEST_METHOD'].upper()
# 获取请求参数和编码信息
try:
content_length = int(environ.get('CONTENT_LENGTH'))
except (ValueError, TypeError):
content_length = 0
# 通过http的请求头信息, 读取客户端传递的信息(通过http里标识的长度), 读取客户端信息

@cached_property
def GET(self):
# The WSGI spec says 'QUERY_STRING' may be absent.
raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '')
return QueryDict(raw_query_string, encoding=self._encoding)

def _get_post(self):
if not hasattr(self, '_post'):
self._load_post_and_files()
return self._post

def _set_post(self, post):
self._post = post

@cached_property
def COOKIES(self):
raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
return parse_cookie(raw_cookie)

@property
def FILES(self):
if not hasattr(self, '_files'):
self._load_post_and_files()
return self._files

POST = property(_get_post, _set_post)

通过分析request对象可以看到, Django里面的WsgiRequest主要做了下面几件事:

  • 通过wsgi服务器传递的enviroment来构建自己的元信息META、Cookie、method等

  • 通过通过将从enviroment里面读取的数据转换成内部对象QueryDict等来方便使用

  • 将HTTP的请求的数据包装成GET、POST和FILES等属性屏蔽底层细节

WSGIRequest是对Dango中的HttpRequest的一个上层封装, 真正对WSGI传递过来数据的操作其实是由HttpRequest类来实现底层对应数据的组合和封装的

今天就分析到这里, 明天继续, 感兴趣的可以加群一起交流Dajngo的学习, QQ群: 279472055


本文分享自微信公众号 - 图解源码(sreguide)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部