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中横向扩展和一 ...
随机推荐
- Android学习笔记_69_android 支付宝之网页支付和快捷支付
参考资料: https://b.alipay.com/order/productDetail.htm?productId=2013080604609654 https://b.alipay.com/o ...
- data-ng-hide 指令
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- Vue node.js商城-购物车模块
一.渲染购物车列表页面 新建src/views/Cart.vue获取cartList购物车列表数据就可以在页面中渲染出该用户的购物车列表数据 data(){ return { car ...
- JS继续学习记录(一)
JS继续学习记录(一) 总感觉自己的js code写的还算可以,但是又深知好像只知道一些皮毛,所以打算仔细记录一下js晋级学习过程,日日往复 先记录一下自己目前对js的了解吧(20180828) js ...
- 微信小程序全局/页面配置
flex布局 父元素 display:flex; flex-direction: row; justify-content:space-between 补充 flex-direction属性决定主轴的 ...
- Vue--- mint-UI 穿插
Vue-mint-UI库 概述:就是一个 封装好的库 安装/下载:npm install --save mint-ui 常用 1) Mint UI:a. 主页: http://mint-ui.git ...
- Graylog2日志服务安装配置
软件版本: mongodb-org-3.2.10 jdk-1.8.0 (推荐rpm包,不然要修改Graylog启动脚本定义的JAVA命令路径) elasticsearch-2.4.1 (Graylog ...
- js | javascript获取和设置元素的属性
获取和设置元素的内容: var nv = document.getElementById("pid"); alert(nv.innerHTML); nv.innerHTML=&qu ...
- 剑指offer—从头到尾打印链表
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 递归添加...不为空就加 import java.util.ArrayList; public class Solution { pu ...
- raid概述与CentOS7.4中raid5的搭建与测试
前言 一.raid的定义与作用 raid(独立冗余磁盘阵列).raid技术通过把多个硬盘设备组合成一个容量更大的,安全性更好的磁盘阵列.把数据切割成许多区段后分别放在不同的物理磁盘上,然后利用分散读写 ...