#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response class TestView(APIView): def get(self, request, *args, **kwargs): # self.dispatch print(request.user) print(request.auth) return Response('GET請求,響應內容') def post(self, request, *args, **kwargs): return Response('POST請求,響應內容') def put(self, request, *args, **kwargs): return Response('PUT請求,響應內容')
Django rest_Framework的基本流程:請求剛進來,會執行dispatch方法,大概的流程以下:第一步封裝request,第二步:版本python
第三步:認證->request.user,第三步:權限->self.check_permissions(request),第四步:節流self.check_throttles(request)django
之前就是Django rest_Framework的基本流程。app
認證的源碼以下(只有認證源碼流程):ide
在上面剛開始請求進來,先不執行本身寫的方法,如:(get、post、put),它會先執行dispatch方法,若是沒有,就回去它的父類去找。函數
執行它父類的dispachpost
Django rest framework流程:this
原來用CBV的時候它繼承from django.views import View中的views方法,在寫get,post方法 如:class HostView(view)spa
若是有Django rest Framework它就不用繼承from django.views import View中的views方法,而是:rest
先導入:from rest_framework.views import APIView它就會繼承APIView,不在繼承django的views如:class AuthView(APIView):code
from rest_framework.views import APIView 先導入APIView
from django.shortcuts import render,HttpResponse
class AuthView(APIView): 繼承APIView authentication_classes=[] def get(self,request):return Response('....’)
而在class AuthView(APIView)中它繼承的APIView,而APIView它有繼承了view,view它在rest_framework view 中以下圖:
點擊view它就會到django的view中,而這個view是之前CBV 中的那個view,以下圖:
繼承的這個類比原來django的這個類跟多了點功能,而它的本質仍是和原來的同樣先執行dispatch,本身有就執行本身的,沒有就執行父類的,父類若是沒有它就執行原來的dispatch 。
雖然之前它的本質同樣可是如今卻發生變化,如今它的request是rest_framework中的request,而原來的request是django中的request,如:
class HostView(APIView): def get(self,request,*args,**kwargs): # 原來request對象,django.core.handlers.wsgi.WSGIRequest # 如今的request對象,rest_framework.request.Request\ self.dispatch 請求進來先執行dispatch print(request.user) print(request.auth) return Response('主機列表')
一、請求進來先執行dispatch,而dispatch它在APIView中,dispatch在它裏面有,先執行它本身,若是把它先刪除它就會先執行默認的那個就是django提供,以下圖:
請求進來它源碼就是從如今開始以下:
源碼的第一步:
def dispatch(self, request, *args, **kwargs): 請求進來先執行dispatch """ `.dispatch()` is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling. """ self.args = args dispatch先把參數獲取到 self.kwargs = kwargs
#一、對request進行加工
'''
源碼進來的第一步 一、request對象中(它比原來的類中封裝了好多):
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(), 這裏面放的是兩個列的對象
negotiator=self.get_content_negotiator(),
parser_context=parser_context
''' request = self.initialize_request(request, *args, **kwargs) 在這執行了這個方法,它返回了request self.request = request self.headers = self.default_response_headers # deprecate? try:
第二步:2 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 第三步:3.執行get/post/delete/put等函數 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
在執行 request = self.initialize_request(request, *args, **kwargs)時,先去本身寫的找,沒有再去父類找,上面是本身沒有就去父類找,以下圖:
上面沒有就去拿它的靜態字段,以下圖:
在這上面執行時request被加工,以下圖:
源碼執行的第二步:
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.
2.1處理版本信息 version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
2.2認證受權 self.perform_authentication(request)
2.3權限驗證 self.check_permissions(request)
2.4請求用戶限制訪問頻率 self.check_throttles(request)
執行源碼第二步中的2.2認證受權:
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)
仍是先找本身的,沒有才執行如下的:
def perform_authentication(self, request): """ Perform authentication on the incoming request. Note that if you override this and simply 'pass', then authentication will instead be performed lazily, the first time either `request.user` or `request.auth` is accessed. """ request.user 在這裏request是傳過來的request,不是原來的request
盡接着下一步它就會找user,以下圖:
找到user :
def user(self): """ Returns the user associated with the current request, as authenticated by the authentication classes provided to the request. """ if not hasattr(self, '_user'): 若是沒有user self._authenticate() 就會這行self._authenticate()這個方法,在找到這個方法
return self._user
def _authenticate(self): """ Attempt to authenticate the request using each authentication instance in turn. """
循環對象列表 for authenticator in self.authenticators: 在這裏authenticators是那個對象列表,它循環這個對象列表 try:
執行每個對象authenticate方法 user_auth_tuple = authenticator.authenticate(self) 在這裏它返回了兩個值 except exceptions.APIException: 沒有驗證成功就會報錯 self._not_authenticated() raise if user_auth_tuple is not None: self._authenticator = authenticator self.user, self.auth = user_auth_tuple 這裏self.auth,self.user,就會有值,驗證成功就會經過 return self._not_authenticated()