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

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

1、as_view()

咱們仍是先從URLconfig中入手,因爲BookView是一個基於類的視圖,因此咱們將URL指向as_view()類方法django

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

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

安裝Django RestFramework源碼分析

pip install djangorestframework

BookView視圖類post

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()url

@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()方法spa

以前的博客介紹過,as_view()方法會返回self.dispatch() ,因爲BookView沒有實現這個方法,因此咱們查看APIView中dispatch()都作了哪些工做rest

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

# 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請求對象進行了從新封裝csrf

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對象。

相關文章
相關標籤/搜索