Django-rest-framework源碼分析(一)

1、APIView

  入口

  在路由層執行as_view()方法前端

  rest-framework/views.py/class APIView/def as_view()

  

  能夠看到,APIView繼承了Django原生的View,而且重寫了as_view()方法,在APIView的as_view方法中,除了一處類中是否有queryset屬性的斷定,as_view主要實現的功能是將原來返回的函數對象view加入裝飾器裝飾,使之能夠被csrfmiddleware中間件的校驗忽略,由於咱們沒法從前端獲取csrf_token。若是不採用這種方法,咱們不得不由用該中間件,這就影響了咱們繼續正常使用Django原生框架。django

  django/views/base.py/class View/def as_view()

  在Django原生的View類的as_view方法中,返回的函數對象view是一個閉包函數,該函數被裝飾器csrf_exempt裝飾後返回到路由層,在路由層被執行,在執行view時,view返回的是dispatch方法執行的結果。閉包

  在APIView類中重寫了dispatch方法,因此上圖紅框內執行的是APIView的dispatch方法。框架

  rest-framework/views.py/class APIView/def dispatch()

  

  rest-framework/views.py/class APIView/def initialize_request()

  

  該方法返回了一個Request對象,Request類是一個restframework對Django原生的request進行封裝的類,它保留了原生的request對象,做爲新實例化request對象的_request屬性,而且擁有原生的request對象的全部屬性和方法。函數

  rest-framework/views.py/class APIView/def dispatch()

  

  回到dispatch方法,這裏的if判斷利用了反射,將咱們本身寫的get,post等方法取出,且讓變量handle指向該方法。self.http_mehtod_names是一個列表,其中包含HTTP八個請求名稱的字符串(['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'])。post

   

  rest-framework/views.py/class APIView/def finalize_response()

  

  咱們看到,在finalize_response函數中,傳入了response參數,而且對其進行了一些封裝,加入了屬性,以及用斷言進行校驗。spa

  response是handle調用後返回的結果,handle則是咱們本身寫的對應HTTP請求的方法,咱們在方法中最後返回了一個HttpResponse對象。在dispatch方法中,主要是用反射,對HTTP請求的類型進行對應方法的分發。rest

 

 2、Request類

  rest-framework/request.py/class Request

  

  能夠看到,Django原生的request對象被做爲參數傳入,封裝進了restframework Request類實例化對象的_request屬性中,在實例化時,還給新的Request對象加入了新的屬性和方法。其中Empty是一個用來佔位的空白類。csrf

  當咱們想執行Django原生的request對象的方法或者想要獲取原生request對象的屬性時,在class Request中重寫了__getattr__(self,attr)方法,該魔法方法在對象獲取屬性時,當該對象找不到屬性時執行。中間件

  rest-framework/request.py/class Request/def __getattr()__

  

  當新request對象的屬性或者方法不存在時,在原生的request對象中尋找,若是也不存在,會拋一個AttributeError異常,這裏作了異常捕獲後,交給__getattribute__()去執行。在Response中沒有重寫__getattribute__()方法,當屬性不存在時,重寫的__getattr__截獲了屬性查找,若是_request仍然沒有找到該屬性,就要交給新式類本身的__getattribute__去執行,以保證該類的屬性查找正常運行。

 

3、Serializer

  restframework/serializers.py/class Serializer

 

  Serializer類繼承了BaseSerializer,而且沒有重寫__init__和__new__方法,因此當該類實例化產生對象的時候,調用的是父類BaseSerializer的__init__和__new__方法。

  restframework/serializers.py/class BaseSerializer

  

  先執行__new__方法,實例化一個空對象,在實例化對象的時候,有可能以關鍵字傳參的形式傳入many參數,該參數在__new__方法中被**kwargs接受,放入字典中。

  __new__中的if判斷是將many取出,當many的Boolean值爲false或者many參數沒有傳入的時候,不執行if下面的語句,也就是會正常實例化一個對象,__new__並未對對象的建立過程作攔截。若是many中有值而且其Boolean不爲false時,會執行many_init方法。

  restframework/serializers.py/class BaseSerializer/def many_init()

   在執行many_init方法時,返回的是一個ListSerializer對象。具體執行過程已經在圖上標出。

  將QuerySet對象而不是數據對象做爲參數,進行序列化時,必須寫many=True(必須用關鍵字傳參的形式)。

相關文章
相關標籤/搜索