Django 源碼小剖: Django 中的 WSGI


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

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

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

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

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

具體內部做了一些變更:

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

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

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: 端口, 自定義端口

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM