Django源码分析之server
乍见
Django内置的server基本包括两部分:django.core.servers和django.core.handlers
相识
servers.basehttp是Django自身提供的一个用于开发测试的server模块,其中提供的WSGIServer、ServerHandler、WSGIRequestHandler其实都是属于WSGI server,django只不过是对python内置的WSGI模块simple_server做的一层包装。
handlers package包括base.py和wsgi.py两个模块。
base.py中只定义了一个BaseHandler类,它复杂一些基础的功能,比如加载中间件,处理异常,获取响应数据等
wsgi.py才是主角,其中最重要的就是WSGIHandler类,它继承了base.py中的BaseHandler,只添加了一个__call__方法,那为什么添加这个方法呢?
django.core.wsgi
import django
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.
"""
django.setup()
return WSGIHandler()
可见我们启动server时传入的application其实是WSGIHandler的一个实例,而根据WSGI规范,这个application必须要是callable,python中的callable包括函数、方法以及任何定义了__call__方法的对象
回到handlers.wsgi
class WSGIHandler(base.BaseHandler):
initLock = Lock()
request_class = WSGIRequest
def __call__(self, environ, start_response):
# Set up middleware if needed. We couldn't do this earlier, because
# settings weren't available.
if self._request_middleware is None:
with self.initLock:
try:
# Check that middleware is still uninitialized.
if self._request_middleware is None:
self.load_middleware()
except:
# Unload whatever middleware we got
self._request_middleware = None
raise
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ)
try:
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:
response = self.get_response(request)
response._handler_class = self.__class__
status = '%s %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)
return response
由于__call__是一个请求的入口,它需要调用BaseHandler中定义的方法去执行加载中间件等一系列操作和异常处理,除此之外,WSGIHandler还会处理cookie、触发signal等。
至于如何返回响应,具体可看handlers.base模块,大概就是找出请求的path,通过匹配路由,找到并执行用户定义的view方法,执行中间件处理方法,最后返回响应。当然,还有一系列的异常处理。
回想
这部分的内容需要对WSGi协议有个大致的了解,可以参考:http://xiaorui.cc/2016/04/16/%E6%89%93%E9%80%A0mvc%E6%A1%86%E6%9E%B6%E4%B9%8Bwsgi%E5%8D%8F%E8%AE%AE%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9%E5%8F%8A%E6%8E%A5%E5%8F%A3%E5%AE%9E%E7%8E%B0/
Django源码分析之server的更多相关文章
- django源码分析 python manage.py runserver
django是一个快速开发web应用的框架, 笔者也在django框架上开发不少web应用,闲来无事,就想探究一下django底层到底是如何实现的,本文记录了笔者对django源码的分析过程 I be ...
- Django源码分析之启动wsgi发生的事
前言 好多人对技术的理解都停留在懂得使用即可,因而只会用而不会灵活用,俗话说好奇害死猫,不然我也不会在凌晨1.48的时候决定写这篇博客,好吧不啰嗦了 继续上一篇文章,后我有个问题(上文:&qu ...
- django源码分析——本地runserver分析
本文环境python3.5.2,django1.10.x系列 1.根据上一篇文章分析了,django-admin startproject与startapp的分析流程后,根据django的官方实例此时 ...
- 2、Django源码分析之启动wsgi发生了哪些事
一 前言 Django是如何通过网络socket层接收数据并将请求转发给Django的urls层? 有的人张口就来:就是通过wsgi(Web Server Gateway Interface)啊! D ...
- Apache Kafka源码分析 – Broker Server
1. Kafka.scala 在Kafka的main入口中startup KafkaServerStartable, 而KafkaServerStartable这是对KafkaServer的封装 1: ...
- Kafka源码分析(三) - Server端 - 消息存储
系列文章目录 https://zhuanlan.zhihu.com/p/367683572 目录 系列文章目录 一. 业务模型 1.1 概念梳理 1.2 文件分析 1.2.1 数据目录 1.2.2 . ...
- django源码分析
原文网址 https://www.jianshu.com/p/17d78b52c732?utm_campaign=maleskine&utm_content=note&utm_medi ...
- django源码分析——处理请求到wsgi及视图view
本文环境python3.5.2,django1.10.x系列 根据前上一篇runserver的博文,已经分析了本地调试服务器的大致流程,现在我们来分析一下当runserver运行起来后,django框 ...
- kafka源码分析之一server启动分析
0. 关键概念 关键概念 Concepts Function Topic 用于划分Message的逻辑概念,一个Topic可以分布在多个Broker上. Partition 是Kafka中横向扩展和一 ...
随机推荐
- python—递归函数
递归函数 定义:即在函数定义中自己调用自己 递归就是在过程或函数中自我调用 递归必须有递归出口,即递归结束条件 举个栗子-阶乘: def fact(n): if n == 1: return 1 re ...
- ASP.NET mvc 验证码 (转)
ASP.net 验证码(C#) MVC http://blog.163.com/xu_shuhao/blog/static/5257748720101022697309/ 网站添加验证码,主要为防止机 ...
- 课时11.HTML基本机构详解(掌握)
通过观察我们发现,HTML基本结构中所有标签都是成对出现的.这些成对出现的标签中有一个带/有一个不带/,那么这些不带/的标签我们称之为开始标签,这些带/的标签,我们称之为结束标签. html标签 作用 ...
- sprinbboot 热部署 造成类加载器 不一致问题
这里只说devtools的方式,注意以下的热部署方式在IDEA是默认没有打开自动编译的,手动编译需要快捷键(Ctrl+Shift+F9), 自动编译的修改配置如下:(注意刷新不要太快,会有1-2秒延迟 ...
- WPF窗口模板——Style样式
通用模板,窗口样式 <!-- 通用窗口模板 --> <ControlTemplate x:Key="CustomWindowTemplate" TargetTyp ...
- navicat 链接oracle时出现的各种问题
1.出现12514错误: 方法:在oracle的安装路径下找到tnsnames.ora文件(我的安装路径为E:\app\sa\product\12.2.0\dbhome_1\network\admin ...
- 工具类(过滤接口空值, value 或 空字符串) - iOS
为了便于日常开发效率,因此创建了一些小的工具类便于使用.具体 code 如下:声明: #import <Foundation/Foundation.h> #import <UIKit ...
- nodejs+express开发blog(2)
npm install -g nodemon 1,把ejs文件修改为html文件 app.engine('.html', require('ejs').__express);app.set('view ...
- 【PTA 天梯赛训练】修理牧场(哈夫曼树+优先队列)
农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li个长度单位,于是他购买了一条很长的.能锯成N块的木头,即该木头的长度是Li的总和. 但是农夫自己没有锯子,请 ...
- Markdown基本使用
最近在写毕业论文,打算列个提纲,觉得有条理的搜集资料规划布局很重要,用Markdown写即有利于增强我的编写接口文档能力,也便于查看. markdown编写软件很多,markdownpad不错(mar ...