Django(51)drf渲染模組原始碼分析

Silent丿丶黑羽發表於2021-06-08

前言

渲染模組的原理和解析模組是一樣,drf預設的渲染有2種方式,一種是json格式,另一種是模板方式。
 

渲染模組原始碼入口

入口:APIView類中dispatch方法中的:self.response = self.finalize_response(request, response, *args, **kwargs)
 

渲染模組原始碼分析

我們首先點選finalize_response進入檢視原始碼

def finalize_response(self, request, response, *args, **kwargs):
    """
    Returns the final response object.
    """
    # Make the error obvious if a proper response is not returned
    # 斷言是否是HttpResponseBase物件
    assert isinstance(response, HttpResponseBase), (
        'Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` '
        'to be returned from the view, but received a `%s`'
        % type(response)
    )
    
    # 判斷是否是Response物件
    if isinstance(response, Response):
        if not getattr(request, 'accepted_renderer', None):
            # 渲染模組的正式入口
            neg = self.perform_content_negotiation(request, force=True)
            request.accepted_renderer, request.accepted_media_type = neg

        response.accepted_renderer = request.accepted_renderer
        response.accepted_media_type = request.accepted_media_type
        response.renderer_context = self.get_renderer_context()

    # Add new vary headers to the response instead of overwriting.
    vary_headers = self.headers.pop('Vary', None)
    if vary_headers is not None:
        patch_vary_headers(response, cc_delim_re.split(vary_headers))

    for key, value in self.headers.items():
        response[key] = value

    return response

上述程式碼是響應模組的原始碼,該原始碼中包含了渲染模組的原始碼,就是這句neg = self.perform_content_negotiation(request, force=True),我們可以點選檢視

def perform_content_negotiation(self, request, force=False):
    """
    Determine which renderer and media type to use render the response.
    """
    # 確定使用哪種渲染器和媒體型別來渲染響應。
    # 渲染器列表
    renderers = self.get_renderers()
    conneg = self.get_content_negotiator()

    try:
        return conneg.select_renderer(request, renderers, self.format_kwarg)
    except Exception:
        if force:
            return (renderers[0], renderers[0].media_type)
        raise

程式碼中有個get_renderers就是渲染器列表,點選檢視

def get_renderers(self):
    """
    Instantiates and returns the list of renderers that this view can use.
    """
    return [renderer() for renderer in self.renderer_classes]

這就是渲染器列表的原始碼,跟解析器列表的原始碼大同小異,接著再點選renderer_classer檢視

renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES

到這裡我們就知道了,drf預設的渲染器在settings下的DEFAUIT_RENDERER_CLASSES中,配置如下

'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],

如果我們想區域性配置渲染器,只需在自己定義的檢視類中新增render_classes 即可,一般也不用做修改,以上分析只是讓大家知道drf是怎麼配置渲染器的,這樣以後我們自定義渲染器也就十分簡單了

相關文章