django源碼分析 請求流程

1、從瀏覽器發出一個請求,到返回響應內容,這個過程是怎麼樣的?

1. 瀏覽器解析輸入的urlnginx

2. 查找url對應的ip地址django

3. 經過ip地址訪問咱們的服務器瀏覽器

  1.  請求進入wsgi服務器(我在這裏省略了可能存在的代理服務器,好比nginx)服務器

  2.  wsgi服務器將請求包裝後,傳遞給django應用cookie

  3.  django應用根據請求路徑找到相應的處理函數進行處理app

  4.  處理完成後,django應用將響應返回給wsgi服務器函數

  5. wsgi服務器將django應用返回的響應包裝後,返回響應post

4. 服務器返回響應內容,瀏覽器渲染輸出atom

2、django應用程序的處理入口

wsgi服務經過wsgi協議和django應用進行通訊,wsgi服務是server端,django應用是application,server端經過django提供的application_callable函數去調用djano應用,application_callable函數處理完成後,將響應返回給serverurl

django的application_callable函數在django.core.handlers.wsgi.py文件中,server服務端處理每一個請求時會調用WSGIHandler這個類

 

#wsgi.py文件

class
WSGIHandler(base.BaseHandler): request_class = WSGIRequest def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.load_middleware() def __call__(self, environ, start_response): set_script_prefix(get_script_name(environ)) signals.request_started.send(sender=self.__class__, environ=environ) request = self.request_class(environ) response = self.get_response(request) response._handler_class = self.__class__ status = '%d %s' % (response.status_code, response.reason_phrase) response_headers = list(response.items()) for c in response.cookies.values(): response_headers.append(('Set-Cookie', c.output(header=''))) start_response(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

 

3、django處理請求流程

WSGIHandler類在初始化時,首先加載中間件,將要請求的函數 _get_response用中間件封裝起來(中間件至關於裝飾器),執行的時候,中間件就會執行

 
 
# wsgi.py文件
def load_middleware(self):
  ...

self._view_middleware
= [] self._template_response_middleware = [] self._exception_middleware = [] handler = convert_exception_to_response(self._get_response) for middleware_path in reversed(settings.MIDDLEWARE): middleware = import_string(middleware_path) try: mw_instance = middleware(handler) except MiddlewareNotUsed as exc:        ...

handler = convert_exception_to_response(mw_instance) self._middleware_chain = handler

 接下來,就是請求調用WSGIHandler

1. 實例化一個request_class

2. 經過get_response獲取請求,get_response最終會調用被中間件封裝後的函數 _get_response 

def _get_response(self, request):
    response = None

    if hasattr(request, 'urlconf'):
        urlconf = request.urlconf
        set_urlconf(urlconf)
        resolver = get_resolver(urlconf)
    else:
        resolver = get_resolver()

    resolver_match = resolver.resolve(request.path_info)
    callback, callback_args, callback_kwargs = resolver_match
    request.resolver_match = resolver_match

    ...

    if response is None:
        wrapped_callback = self.make_view_atomic(callback)
        try:
            response = wrapped_callback(request, *callback_args, **callback_kwargs)
        except Exception as e:
            response = self.process_exception_by_middleware(e, request)

    ...

    return response

_get_response函數中,首先會根據url找到要調用的視圖函數 resolver_match = resolver.resolve(request.path_info),而後調用視圖函數 response = wrapped_callback(request, *callback_args, **callback_kwargs)返回response(在_get_response裏面也是會調用一些的中間件的)

至此再將response返回給server,整個請求流程完畢

下面是這個過程的流程圖

我也以一種函數的形式,寫了一下這個流程

 

def process_request(request)
    try:
        # 請求前的中間件
        response = pre_middleware(request)
        if response:
            return response
        
        # 視圖中間件
        response = view_middleware(request, view_fun)
        
        if not response:
            try:
                # 執行視圖函數
                reponses = view_fun(request)
            except:
                # 異常中間件
                responser = exception_middleware()
        
        if hasattr(response, 'render'):
            # 模板中間件
            response = template_middleware(response)
            try:
                response = response.render()
            except:
                response = exception_middleware()
        
        # 請求後的中間件
        response = post_middleware(request, response)
            
    except:
        response = exception()
        
    return response

 

4、總結

django對於一個請求,主要過程就是尋找請求對應的視圖函數,調用被中間件封裝後的視圖函數,返回響應。

相關文章
相關標籤/搜索