DRF源碼理解

DRF 的 APIView 繼承 View

  • django 的 View
  • DRF 的 APIView
  • dispatch 中,對request進行加強


  • APIView 調(diào)用了 View 的 as_view 方法
    view = super(APIView, cls).as_view(**initkwargs)
    
  • View 調(diào)用了 APIView 的 dispatch 方法
    self.dispatch(request, *args, **kwargs)
    
  • dispatch 方法加強了原生 request
    # 第一次的加強(添加方法)
    request = self.initialize_request(request, *args, **kwargs)
    # 第二次的調(diào)用(調(diào)用方法)
    self.initial(request, *args, **kwargs)
    


>>>源碼


>>> 第一次的加強(1)
def initialize_request(self, request, *args, **kwargs):
    """
    Returns the initial request object.
    """
    parser_context = self.get_parser_context(request)
    # 對request進行了加強
    return Request(
        request,    # Django原本的request
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),  # 與認證相關(guān)
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )
>>> 第一次的加強(2)
# 認證
def get_authenticators(self):
    """
    Instantiates and returns the list of authenticators that this view can use.
    """
    return [auth() for auth in self.authentication_classes]

# 讀配置
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES


>>>第二次的調(diào)用(1)
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)  # 認證 token / 匿名
    self.check_permissions(request)       # 權(quán)限 /  誰能訪問什么內(nèi)容
    self.check_throttles(request)         # 限流  60/分
>>> 第二次的調(diào)用(2)
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  # 驗證用戶身份方法
>>> 第二次的調(diào)用(3)
# rest_framework.request.py 文件內(nèi)
@property
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'):
        with wrap_attributeerrors():
            # 獲取認證對象 一步步認證
            self._authenticate()
    return self._user
  • 我們可以寫一個自己的登錄認證

from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions

class MyAuthentication(BaseAuthentication):
    def authenticate(self, request, *args, **kwargs):
        if not  request._request.GET.get('token')  # 拿request 對象的屬性:
           raise exceptions.AuthenticationFailed('認證失敗')
        return ("海綿寶寶", None)

# views.py
class xxx(APIView):
    authentication_classes = [MyAuthentication]
    ...
>>> 第二次的調(diào)用(4)
def _authenticate(self):
    """
    Attempt to authenticate the request using each authentication instance
    in turn.
    """
    for authenticator in self.authenticators:
        try:
            # 如果是自定義方法,調(diào)用自己的方法
            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
            return

    self._not_authenticated()
  • tips:多認證(多個認同時滿足)
  • 應(yīng)用場景:人臉識別、高級安全、資金提現(xiàn)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容