Django 源碼小剖: Django 中的 WSGI

Django 其內部已經自帶了一個方便本地測試的小服務器, 因此在剛開始學習 Django 的時候並不需搭建 apache 或者 nginx 服務器. Django 自帶的服務器基於 python wsgiref 模塊實現的, 其百分之七八十的代碼都是 wsgiref 中的代碼, 只重寫了一部分, 因此 Django 自帶的服務器測試寫個 helloworld 就行了.python

Django 內置服務器在 django.core.servers 和 django.core.handlers, 這二者共同來實現.先看看 django.core.servers. 下面是目錄結構:nginx

E:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\SERVERS
basehttp.py 重寫 ServerHandler,WSGIServer,WSGIRequestHandler,定義 run() 函數
fastcgi.py
__init__.pygit

下面的代碼足以說明「百分之七八十」:github

class ServerHandler(simple_server.ServerHandler, object):
...
class WSGIServer(simple_server.WSGIServer, object):
...
class WSGIRequestHandler(simple_server.WSGIRequestHandler, object):

具體內部作了一些變動:apache

  • 重寫了 write 函數, 當傳輸數據過大的時候分段傳輸
  • 多了一些異常處理
  • 錯誤記錄

都是無關痛癢, 不詳細展開了.這裏定義了一個頗有意思的函數 run():django

def run(addr, port, wsgi_handler, ipv6=False, threading=False):
    server_address = (addr, port)

    if threading:
        httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})
    else:
        httpd_cls = WSGIServer

    httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
    httpd.set_app(wsgi_handler)
    httpd.serve_forever() 永久運行

這和上一篇 if __name__ == '__main__': 中的代碼效果相似, 實例化服務器類, 讓它跑起來. 在 run() 函數中能夠根據喜愛配置:服務器

add: 地址, 可傳入 ip 地址, 通常是 127.0.0.1多線程

port: 端口, 自定義端口app

wsgi_handler: 上節提到的 application, 在 django.core.handlers 中定義socket

ipv6: 若是爲 true, 會將協議地址族換成是 AF_INET6

threading: 若是爲 true, 服務器會被強制成 type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})(這個我漏講了, 但功能是這樣), 能處理多線程處理請求.

因此, 調用這個函數能夠讓一個自定義服務器跑起來.

wsgi_handler 參數定義了 application, 而 application 必須是一個 start_response(status, response_headers, exc_info=None) 形式的函數或者定義了 __call__ 的類. 而 django.core.handlers 就用後一種方式實現了 application.

E:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\HANDLERS
base.py application 的基類 BaseHandler
wsgi.py 實現 WSGIHandler 類, 定義了 __call__, 這樣就名正言順的 WSGI 中的 application 了
__init__.py

事實上, 在 WSGI 中除了 application,server 外, 還有一個 middleware, 名曰中間件. 在上一篇中故意漏了, 由於沒有涉及到.最後我疏離一下上邊提到的類模塊等等, 方便你們找源碼, 整理以下:

C:\PYTHON27\LIB\WSGIREF
handlers.py 定義了 BaseHandler, SimpleHandler 類
headers.py
simple_server.py 定義了 ServerHandler, WSGIRequestHandler 類, demo_app(), make_server()
util.py
validate.py
__init__.py

E:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\SERVERS
basehttp.py 重寫 ServerHandler,WSGIServer,WSGIRequestHandler,定義 run() 函數
fastcgi.py
__init__.py

E:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\HANDLERS
base.py application 的基類 BaseHandler
wsgi.py 實現 WSGIHandler 類, 定義了 __call__, 這樣就名正言順的 WSGI 中的 application 了
__init__.py

ps: 目錄根據實際狀況會不一樣, 看具體狀況.我已經在 github 備份了 Django 源碼的註釋: Decode-Django, 有興趣的童鞋 fork 吧.

搗亂  2013-9-6

http://daoluan.net

相關文章
相關標籤/搜索