美文网首页
DRF源码理解

DRF源码理解

作者: 錦魚 | 来源:发表于2019-11-19 10:48 被阅读0次

    DRF 的 APIView 继承 View

    • django 的 View
    • DRF 的 APIView
    • dispatch 中,对request进行加强

    • APIView 调用了 View 的 as_view 方法
      view = super(APIView, cls).as_view(**initkwargs)
      
    • View 调用了 APIView 的 dispatch 方法
      self.dispatch(request, *args, **kwargs)
      
    • dispatch 方法加强了原生 request
      # 第一次的加强(添加方法)
      request = self.initialize_request(request, *args, **kwargs)
      # 第二次的调用(调用方法)
      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(),  # 与认证相关
            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
    

    >>>第二次的调用(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)       # 权限 /  谁能访问什么内容
        self.check_throttles(request)         # 限流  60/分
    
    >>> 第二次的调用(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  # 验证用户身份方法
    
    >>> 第二次的调用(3)
    # rest_framework.request.py 文件内
    @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]
        ...
    
    >>> 第二次的调用(4)
    def _authenticate(self):
        """
        Attempt to authenticate the request using each authentication instance
        in turn.
        """
        for authenticator in self.authenticators:
            try:
                # 如果是自定义方法,调用自己的方法
                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:多认证(多个认同时满足)
    • 应用场景:人脸识别、高级安全、资金提现

    相关文章

      网友评论

          本文标题:DRF源码理解

          本文链接:https://www.haomeiwen.com/subject/avybictx.html