django Rest Framework----APIView 執行流程 APIView 源碼分析


django—CBV源碼分析中,我們是分析的from django.views import View下的執行流程,這篇博客我們介紹django Rest Framework下的APIView的源碼分析。

一、as_view()

我們還是先從URLconfig中入手,由於BookView是一個基於類的視圖,所以我們將URL指向as_view()類方法

url(r'books/',views.BookView.as_view()),

此時,我們的BookView已經不是繼承自django.views中View了,而是restframework.views中的APIView

安裝Django RestFramework

pip install djangorestframework

BookView視圖類

from django.shortcuts import render,HttpResponse
#導入APIView
from rest_framework.views import APIView

#繼承自APIView
class BookView(APIView):

    def get(self,request):
        return HttpResponse('get....')

    def post(self,request):
        return HttpResponse('post....')

as_view():由於BookView沒有實現as_view()方法,django啟動時,調用的as_view()是APIView中的as_view()

@classmethod
def as_view(cls, **initkwargs):
    """
    將原始類存儲在視圖函數上
    這允許我們在執行url反向查找時發現有關視圖的信息。
    """
    ...
    #由於APIView是繼承自django.views中的View(上篇博客接觸過)
    #調用父類(View)中的as_view()
    view = super(APIView, cls).as_view(**initkwargs)
    view.cls = cls
    view.initkwargs = initkwargs

    # 提示: 基於會話的身份驗證被明確地CSRF驗證
    # 所有其他身份驗證都免予使用CSRF。
    # 跳過CSRF驗證
    return csrf_exempt(view)

在APIView中的as_view()方法什么都沒做,只是調用了父類的as_view()方法

之前的博客介紹過,as_view()方法會返回self.dispatch() ,由於BookView沒有實現這個方法,所以我們查看APIView中dispatch()都做了哪些工作

dispatch():和Djnago.views中View類的dispatch()派遣相同,額外添加了一些功能

# Note: 在“派遣”需要被改寫的情況下,可以在"as_view"范圍內對CSRF進行豁免,以防止意外移除這一豁免。
def dispatch(self, request, *args, **kwargs):
    """
    和django.views中View的dispatch()調度差不多,
    但是有額外的鈎子用於啟動、終結和異常處理。
    """
    self.args = args
    self.kwargs = kwargs
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?
    try:
        self.initial(request, *args, **kwargs)

        # 獲取適當的程序處理方法,這里的調度和django  View的調度一樣
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(),
                              self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        
        # 調用HTTP請求處理方法,並返回
        response = handler(request, *args, **kwargs)

    except Exception as exc:
        response = self.handle_exception(exc)

    self.response = self.finalize_response(request, response, *args, **kwargs)
    return self.response

APIView中的dispatch()和Django中的dispatch()類似,不同之處,APIView對request請求對象進行了重新封裝

request:APIView對request對象進行了重新封裝

def dispatch(self, request, *args, **kwargs):
    """
    `.dispatch()` is pretty much the same as Django's regular dispatch,
    but with extra hooks for startup, finalize, and exception handling.
    """
    self.args = args
    self.kwargs = kwargs
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?
    
    ....

默認的是django.core.handlers.wsgi.WSGIRequest對象,通過調用initialize_request()將其封裝成rest_framework.request.Request。通過type(request)來查看

initialize_request():做了哪些工作

def initialize_request(self, request, *args, **kwargs):
    parser_context = self.get_parser_context(request)

    # 返回了一個reuqest請求對象
    return Request(
        request,
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )

Request類: 完善request請求的一些注意事項,例如用戶登錄、檢測權限等等

class Request(object):

    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        ...
        #將原始的WSGIReqeust對象復制給_request
        self._request = request

        ....

    #調用舊的request.GET
    @property
    def query_params(self):return self._request.GET
    
    #調用舊的request.POST
    @property
    def POST(self):return QueryDict('', encoding=self._request._encoding)    

之后使用的request,都是restfromwork封裝的Reqeust對象。


免責聲明!

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



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