应用程序入口 WSGIHandler
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 中能找到如下设置:
| 1 2 | # Python dotted path to the WSGI application used by Django's runserver.WSGI_APPLICATION ='tomato.wsgi.application' | 
如你所见, WSGI_APPLICATION 就指定了应用程序. 而按图索骥下去, 找到项目中的 wsgi.py, 已经除去了所有的注释:
| 1 2 3 4 5 6 | importosos.environ.setdefault("DJANGO_SETTINGS_MODULE", "tomato.settings")fromdjango.core.wsgi importget_wsgi_applicationapplication =get_wsgi_application() | 
因此, WSGI_APPLICATION 所指定的即为 wsgi.py 中的全局变量 application. 故伎重演, 继续找下去. 在 django.core 模块中的 wsgi.py 中找到 get_wsgi_application() 函数的实现:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | fromdjango.core.handlers.wsgi importWSGIHandlerdefget_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):    """    returnWSGIHandler() | 
在 get_wsgi_application() 中实例化了 WSGIHandler, 并无其他操作.
WSGIHandler
紧接着在 django.core.handler 的 base.py 中找到 WSGIHandler 的实现.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | # 继承, 但只实现了 __call__ 方法, 方便使用classWSGIHandler(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() 没有调用成功.        ifself._request_middleware isNone:            with self.initLock:                try:                    # Check that middleware is still uninitialised.                    ifself._request_middleware isNone:                        因为 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)        exceptUnicodeDecodeError:            logger.warning('Bad Request (UnicodeDecodeError)',                exc_info=sys.exc_info(),                extra={                    'status_code': 400,                }            )            response =http.HttpResponseBadRequest()        else:            # 调用 self.get_response(), 将会返回一个相应对象 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 ='UNKNOWN STATUS CODE'         # 状态码        status ='%s %s'%(response.status_code, status_text)        response_headers =[(str(k), str(v)) fork, v inresponse.items()]        # 对于每个一个 cookie, 都在 header 中设置: Set-cookie xxx=yyy        forc inresponse.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__ 方法. 从 WSGIHandler 的实现来看, 它并不是最为底层的: WSGIHandler 继承自 base.BaseHandler, 在 django.core.handler 的 base.py 中可以找到: class BaseHandler(object):...
这一节服务器部分已经结束, 接下来的便是中间件和应用程序了, 相关内容会在下节的 BaseHandler 中展开. 我已经在 github 备份了 Django 源码的注释: Decode-Django, 有兴趣的童鞋 fork 吧.
近来准备校园招聘, 生产效率较低, 九月份的空气注定不安分 ;)
捣乱 2013-9-11
应用程序入口 WSGIHandler的更多相关文章
- Django 源码小剖: 应用程序入口 WSGIHandler
		WSGI 有三个部分, 分别为服务器(server), 应用程序(application) 和中间件(middleware). 已经知道, 服务器方面会调用应用程序来处理请求, 在应用程序中有真正的处 ... 
- [iOS] 使用xib作为应用程序入口 with IDE
		[iOS] 使用xib作为应用程序入口 with IDE 在「使用xib做为应用程序入口 with Code」这篇文章中,介绍了如何透过写Code的方式,来使用xib做为应用程序的入口.但其实在Xco ... 
- [iOS] 使用xib做为应用程序入口 with Code
		[iOS] 使用xib做为应用程序入口 with Code 前言 开发iOS APP的时候,使用storyboard能够快速并且直觉的建立用户界面.但在多人团队开发的情景中,因为storyboard是 ... 
- 【转载】MFC 程序入口和执行流程
		原文链接: http://www.cnblogs.com/liuweilinlin/archive/2012/08/16/2643272.html 一 MFC程序执行过程剖析 1)我们知道在WIN32 ... 
- 一个简单的mfc单页界面文件读写程序(MFC 程序入口和执行流程)
		参考:MFC 程序入口和执行流程 http://www.cnblogs.com/liuweilinlin/archive/2012/08/16/2643272.html 程序MFCFlie ... 
- 开源GUI-Microwindows之程序入口分析
		**************************************************************************************************** ... 
- MFC 程序入口和执行流程
		MFC(微软基础类库)以C++类的形式封装了Windows API,给开发者提供了便利,但是初学者常常会疑惑MFC程序的入口在哪里?下面给大家简单介绍一下MFC 程序入口和执行流程. 一 MFC程序执 ... 
- 亲测实验,stm32待机模式和停机模式唤醒程序的区别,以及唤醒后程序入口
		这两天研究了STM32的低功耗知识,低功耗里主要研究的是STM32的待机模式和停机模式.让单片机进入的待机模式和停机模式比较容易,实验中通过设置中断口PA1来响应待机和停机模式. void EXTI1 ... 
- 小程序入口构造工具&二维码测试工具
		小程序入口构造工具&二维码测试工具 本文将介绍我们小程序中隐藏的两个工具页面.原理虽不复杂,收益却实实在在,或许也能给诸君带来启发. 入口构造工具 痛点 PM&运营 投放链接 PM&a ... 
随机推荐
- C#-TextBox-登录表单password无形---ShinePans
			using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ... 
- linux_ssky-keygen + ssh-copy-id 无密码登陆远程LINUX主机
			使用下例中ssky-keygen和ssh-copy-id,仅需通过3个步骤的简单设置而无需输入密码就能登录远程Linux主机. ssh-keygen 创建公钥和密钥. ssh-copy-id 把本地主 ... 
- NEFUOJ 500 二分法+最大流量
			http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=500 description 在这个信息化的时代.网购成为了最流行的购物方 ... 
- Java设计模式(八)观察者模式 迭代器模式
			(十五)观察者模式 观察者模式,定义对象间一对多关系,一个对象状态发生改变,全部依赖于它的对象都收到通知而且自己主动更新,观察者与被观察者分开.比如邮件订阅.RSS订阅,假设有更新就会邮件通知你. i ... 
- 用python 爬取网页图片
			import re import string import sys import os import urllib url="http://tieba.baidu.com/p/252129 ... 
- 继续推荐几款VisualStudio的插件
			原文:继续推荐几款VisualStudio的插件 继前几天推荐了一款转换vs插件的插件后,借着安装VS2013之际,把我比较喜欢的几个插件继续推荐一下. C# Outline 2013 2013 C# ... 
- DataTable相关操作,筛选,取前N条数据,获取指定列数据
			DataTable相关操作,筛选,取前N条数据,获取指定列数据2013-03-12 14:50 by Miracle520, 2667 阅读, 0 评论, 收藏, 编辑 1 #region DataT ... 
- C#实现Web文件上传的两种方法
			1. C#实现Web文件的上传 在Web编程中,我们常需要把一些本地文件上传到Web服务器上,上传后,用户可以通过浏览器方便地浏览这些文件,应用十分广泛. 那么使用C#如何实现文件上传的功能呢?下面笔 ... 
- 日积月累系列之省市选择器(js源码)
			省市选择器是大家经常用到的, 但网上找的省市选择器都不是很实用,于是自己写了移动端的省市选择器. 界面: 源码结构: 演示地址:http://component.cform.cn/city/ 演示二维 ... 
- Android设备连接Unity Profiler性能分析器
			Unity提供两种方式让Developer的Android设备连接Profiler进行性能分析: 1.通过wifi,Android设备和计算机处于同一个Wlan中. 2.通过USB ADB 普通情况我 ... 
