1、什麼是rest_framework 它是基於Django的,幫助咱們快速開發符合RESTful規範的接口框架。 安裝方式有不少種,能夠經過pip,或者在pycharm中安裝也能夠 2、APIView 它的做用和from django.views import View中的View做用差很少,APIView是繼承了View,因此執行as_view,dispatch方法都會 先走到APIView這個類中。因此經過這個APIView裏的dispatch進行一層封裝,對request這個對象進行改變,添加了認證、權限、頻率這些 認證。能夠去看看它的源碼。 視圖層(CBV模式): class Login(APIView): 路由層:url(r'login/',views.Login.as_views()) 分析: 程序啓動時:會執行一遍django中的代碼,函數沒有被調用的話,只會檢測其語法是否正確,看到路由層views.Login.as_views(),這是 一個函數加了括號,因此會執行到,as_views這是一個由類去調用並無傳參數的函數,若是不是靜態方法,就是一個類方法, 我Login這個類中沒有as_views這個方法,因此去它的基類(APIView)去找,找到了 as_view(cls,**initkwargs): """ Store the original class on the view function. This allows us to discover information about the view when we do URL reverse lookups. Used for breadcrumb generation. """ if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet): def force_evaluation(): raise RuntimeError( 'Do not evaluate the `.queryset` attribute directly, ' 'as the result will be cached and reused between requests. ' 'Use `.all()` or call `.get_queryset()` instead.' ) cls.queryset._fetch_all = force_evaluation view = super(APIView, cls).as_view(**initkwargs) view.cls = cls view.initkwargs = initkwargs # Note: session based authentication is explicitly CSRF validated, # all other authentication is CSRF exempt. return csrf_exempt(view) # 這行代碼 view = super(APIView, cls).as_view(**initkwargs),它會執行APIView基類(View)中的 as_view方法,獲得一個函數的內存地址,賦值給view 最後return csrf_exempt(view) #csrf_exempt()是否是局部禁用了csrf檢測 因此,在程序啓動了以後,路由層的代碼應該爲url(r'login/',views.Login.csrf_exempt(view)) # 注意其實這裏不是最終的版本,他還會執行csrf_exempt(view),總之views.Login.csrf_exempt(view)的執行結果是一個函數的內存地址 # csrf_exempt這個就是禁用掉csrf認證的裝飾器吧,最後返回的仍是view函數 有請求來的時候: 當有請求走到路由層時,那麼該url對應的函數內存地址便會加括號直接運行,好比url爲login,那麼執行views.Login.view() 經過上面as_view方法,咱們不難找到view方法,APIView中的view,是調用其父類(View)as_view方法,而as_view返回值就是view的內存地址, 那麼view函數的源碼就是下面這些,通過一些判斷,最後返回的是dispatch方法的返回值 def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) view函數的返回值return self.dispatch(request, *args, **kwargs),這裏的self其實就是Login(這個視圖類的對象),因此咱們的查找 順序爲對象名稱空間,而後就是它父類的名稱空間,一層一層往上找,Login這個試圖類是咱們本身寫的,若是本身沒寫dispatch方法的話,那應該就去 它的基類(APIView)去找dispatch,咱們能夠在APIView類中能夠看到有這個dispatch方法,下面列出源碼: 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? try: self.initial(request, *args, **kwargs) # Get the appropriate handler method 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 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 dispatch方法主要看這幾句: ----------------------------------------------------------- request = self.initialize_request(request, *args, **kwargs) ----------------------------------------------------------- self.initial(request, *args, **kwargs) ----------------------------------------------------------- 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 response = handler(request, *args, **kwargs) ----------------------------------------------------------- ############ 好下面來講說注意的第一行代碼:request = self.initialize_request(request, *args, **kwargs) ############ # 我先說它作了什麼事情,不看內部代碼,將self(此時是Login視圖類的對象),執行方法initialize_request方法的返回值賦值給了request, # 其實這句代碼就是從新封裝了request,方法傳入的request對象其實就是沒有被處理過的,通過一頓操做後,返回值request就是rest_framework # 中Request類的對象。下面是initialize_request方法的源碼: def initialize_request(self, request, *args, **kwargs): """ Returns the initial request object. """ parser_context = self.get_parser_context(request) return Request( request, parsers=self.get_parsers(), authenticators=self.get_authenticators(), negotiator=self.get_content_negotiator(), parser_context=parser_context ) 看返回值,就是Request()的實例化吧,這個Request就是rest_framework中的Request類了,括號裏就是傳過去的參數吧,這裏self也是視圖類 的對象(Login),拿一個括號裏的參數來說,其餘參數方式都是同樣,就不一一解釋了。 好比這句:authenticators=self.get_authenticators() 這句代碼不難理解吧,直接self的get_authenticators綁定方法,也多是靜態方法,把返回值賦值給authenticators,我這裏說靜態是光看這 一句代碼能夠看出。點進去看看get_authenticators源碼以下: def get_authenticators(self): """ Instantiates and returns the list of authenticators that this view can use. """ return [auth() for auth in self.authentication_classes] 最終返回的是一個列表,這裏的self仍是視圖類對象(Login),authentication_classes這就是一個屬性對吧,那麼咱們就去找找這個屬性到底 是什麼,self爲視圖類對象,那咱們先從視圖類(Login)找屬性,咱們本身寫的視圖類沒有的話,就去繼承的APIView類中查看。就在該類的最前面部分 有這樣一段代碼:authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES,那就繼續按住ctrl,點擊api_settings 去查看唄,這句代碼api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS),api_settings它是APISettings這個類的對象, 你能夠看到這個常量DEFAULTS,那麼就在當前py文件搜索下,看看哪裏出現過,最終確定能找到,DEFAULTS它是一個字典,這個字典裏就有不少key, value形式,咱們不難找到DEFAULT_AUTHENTICATION_CLASSES這個key對吧: 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication' ) rest_framework.authentication.SessionAuthentication,這樣的形式咱們是否是見過(settings文件中有不少) 咱們能夠經過導模塊的方式,看看這是什麼。 from rest_framework.authentication import SessionAuthentication 能夠看出,這是一個類,那麼,咱們倒着再理解下。注意: api_settings.DEFAULT_AUTHENTICATION_CLASSES ---->>> 是一個元組(列表也是) == [類,類,類] authentication_classes 這個屬性也就是 ---->>> 是一個元組(列表也是) == [類,類,類] 回到最初那個地方 [auth() for auth in self.authentication_classes],列表生成式不難理解,那麼get_authenticators方法返回的 就是[類(),類(),類()] ----->>> 也就是[對象,對象,對象],又回到Request對象的實例了 authenticators=self.get_authenticators(),因此authenticators就是一個[對象,對象,對象],就是裝着對象的列表。 ######總結一下initialize_request這個方法: 1、它最終返回的就是一個Request的對象,這裏的Request再也不是以前那個了,是rest_framework裏的Request對象 2、再看返回值這裏,self.get_authenticators()最終獲得是裝着對象的列表,列表裏的對象是視圖類對象裏的authentication_classes 這個屬性獲得的,而這個屬性它是一個列表(元組也行),裝着對應的類。 提醒幾點:注意你看的源碼,當前的self是誰,還有就是面向對象屬性的查找順序。(先對象名稱空間,它父類的名稱空間,父類繼承基類的名稱空間 ,最後應該就是type吧(type這個的話,我理解是這樣)) ############ 那好繼續下一句注意的代碼,self.initial(request, *args, **kwargs) ############ 這行代碼self.initial(request, *args, **kwargs),它主要作了登錄驗證,權限驗證,頻率驗證,若是一個請求都知足上面這些這些驗證的話, 那麼就會執行到對應的請求方法裏面,好比來一個get請求,那就走到該視圖類get方法中去 下面是self.initial(request, *args, **kwargs)方法的源碼 def initial(self, request, *args, **kwargs): """ Runs anything that needs to occur prior to calling the method handler. """ self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request neg = self.perform_content_negotiation(request) request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use. version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted self.perform_authentication(request) self.check_permissions(request) self.check_throttles(request) 這個方法裏,須要注意的就是最後這三行代碼,我先就說說它是作什麼用的吧,後面我會再挨個挨個寫 ##注意啊,這裏的request是rest_framework中的Request的對象 self.perform_authentication(request) ##它是進行登錄驗證的 self.check_permissions(request) ##它是就行權限驗證的 self.check_throttles(request) ##它是進行頻率驗證的 ############ 好了,繼續下面的代碼: 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 response = handler(request, *args, **kwargs) ############ ##注意啊,這裏的request是rest_framework中的Request的對象 ##很簡單的if判斷邏輯的代碼,我說說大概意思吧, request.method.lower() ---->> 本次請求方法的小寫(get,post,put等等) self.http_method_names ---->> 這裏的self就是視圖類對象,http_method_names就是一個列表,裝着請求方法的小寫 這是很基本的面向對象的屬性查找,本身看查找看看,看看在哪一個類裏? handler = getattr(self,A,B) ---->> 面向對象裏的反射,若是在self中有A的話,那麼handler就是A的內存地址,沒有的話就是B的內存地址 response = handler(request, *args, **kwargs) --->> 最終會執行上面獲得的函數內存地址,將返回值賦值給response 這裏就舉個例子,更加明白上面這幾句代碼。 瀏覽器發送一個login的get請求,那麼request.method.lower()就是get,它在http_method_names這個列表裏面,因此handler就是get方法的 內存地址(這裏的get就是視圖類裏寫的get方法),便會執行get這個方法,假如這個get方法的返回值是HttpResponse('login get'), 那麼response就是HttpResponse('login get')。 再寫一個注意的地方,回到dispatch這個方法,裏面是否是有一個try....except捕捉異常的代碼,它有什麼用呢?這個跟進行登錄驗證,權限驗證, 頻率驗證那裏有關係。後面寫這個的時候,我會再寫。 這部分就到此結束吧, 登錄驗證,權限驗證,頻率驗證 後面再寫。 不能密密麻麻寫一大推,而後會發生太長不看(我就是這樣哈哈) 格式可能太差了,沒辦法,想到哪裏寫到哪裏