1. 程式人生 > >Django源碼分析之server

Django源碼分析之server

void 分析 pac war tin elf face erro handlers

乍見

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