• DRF源码分析


    APIView源码分析

    # from rest_framework.views import APIView
    
    # urls.py    
    path('booksapiview/', views.BooksAPIView.as_view()),  # 在这个地方应该写一个函数内存地址
    
    
    # APIView的as_view方法(类的绑定方法)
        @classmethod
        def as_view(cls, **initkwargs):
    
            view = super().as_view(**initkwargs)  # 调用父类(View)的as_view(**initkwargs)
            view.cls = cls  # 参见下图补充
            view.initkwargs = initkwargs
            # all other authentication is CSRF exempt.
            # 以后所有的请求都没有csrf的认证了,只要继承了APIView,就没有了csrf的认证
            return csrf_exempt(view)
        
    # 请求来了--->路由匹配上--->View(request)--->调用了self.dispatch(),会执行APIview的dispatch
       
    # APIView的dispatch方法
     def dispatch(self, request, *args, **kwargs):
    
            self.args = args
            self.kwargs = kwargs
            # self.initialize_request(request, *args, **kwargs) request是当次请求的request
            # request = self.initialize_request  request是一个新的request对象
            # 重新包装成一个request对象,以后再用request对象,就是新的request对象了
            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
    
    views.py中    
    class BooksAPIView(APIView):
        def get(self, request):
            # request已经不是原生django的request了,是drf自己定义的request对象
            # print(self.request)
            print(request.data)
            return HttpResponse('ok')

    图解

    入口

     请求来了--->路由匹配上--->View(request)--->调用了self.dispatch(),会执行APIview的dispatch

     ApiView的dispath

    Request对象

    from rest_framework.request import Request
    # 以后只要继承了APLView,视图中的request对象,都是新的,也就是上面那个request的对象了
    # 老的request在新的request._request
    # 以后使用request对象,就像使用之前的request是一模一样的(重写了__getattr__方法)
    
    def __getattr__(self, attr):
            try:
                # 通过反射,如果要取request.method,是去_request里面去取了
                return getattr(self._request, attr) 
            except AttributeError:
                return self.__getattribute__(attr)
    
            
            
    # request.data  感觉是个数据属性,其实是个方法   @property修饰了
    # 它是一个字典,post请求不管使用什么编码,传过来的数据,都在request.data
     @property
     def data(self):
            if not _hasattr(self, '_full_data'):
                self._load_data_and_files()
            return self._full_data
        
    
    # get请求传过来的数据,从哪里取? request.GET 和 request.query_params都可以
        @property
        def query_params(self):
            """
            More semantically correct name for request.GET.
            """
            return self._request.GET
        
        # views.py中 : 
        print(request.query_params)  # get请求,地址中的参数
        # 原来在request.GET
        print(request.GET)

    图解

    重新包装成一个request对象,以后再用request对象,就是新的request对象了

     

    重写了getattr,通过反射,如果要取request.method,是去_request里面取

    以后使用request对象,就像使用原来的request对象一样

    request.data

    request.query_params

    APIView的initial(三大认证模块)

    def initial(self, request, *args, **kwargs):
        # 认证组件:校验用户 - 游客、合法用户、方法用户
        # 游客:代表校验通过,直接进入下一步校验(权限校验)
        # 合法用户:代表校验通过,将用户存储在request.user中,再进入下一步校验(权限校验)
        # 非法用户:代表校验失败,抛出异常,返回403权限异常结果
        self.perform_authentication(request) 
        # 权限组件:校验用户权限 - 必须登录、所有用户、登录读写游客只读、自定义用户角色
        # 认证通过:可以进入下一步校验(频率认证)
        # 认证失败:抛出异常,返回403权限异常结果
        self.check_permissions(request)
        # 频率组件:限制视图接口被访问的频率次数 - 限制的条件(IP、id、唯一键)、频率周期时间(s、m、d)、频率的次数(3/s)
        # 没有达到限次:正常访问接口
        # 达到限次:限制时间内不能访问,限制时间达到后,可以重新访问
        self.check_throttles(request)

    图解

    many=True源码分析

    # 序列化多条,需要传many=True
    
    
    # 对象的生成 ---> 先调用类的__new__方法,生成空对象
    # 对象=类名(name=lqz),触发类的__init__()
    # 类的__new__方法控制对象的生成
        def __new__(cls, *args, **kwargs):
            if kwargs.pop('many', False):
                return cls.many_init(*args, **kwargs)
            # 没有传many=True,走下面,正常的对象实例化
            return super().__new__(cls, *args, **kwargs)

    图解

    认证的源码分析

    # 1 APIView ---> dispatch方法 ---> self.initial(request, *args, **kwargs) ---> 有认证,权限,频率
    # 2 只读认证源码: self.perform_authentication(request)
    # 3 self.perform_authentication(request)就一句话request.user,需要去drf的Request对象中找user属性(方法)
    # 4 Request类中的user方法,刚开始来,没有user,走self._authenticate()
    
    # 5 核心:就是Request类的_authenticate(self):
        def _authenticate(self):
            # 遍历拿到一个个认证器,进行认证
            # self.authenticators配置的一堆认证类产生的认证类对象组成的 list
            # # self.authenticators 是你在视图类中配置的一个个的认证类:authentication_classes = [认证类1,认证类2...] 对象的列表
            for authenticator in self.authenticators:
                try:
                    # 认证器(对象)调用认证方法authenticate(认证类对象self,request请求对象)
                    # 返回值:登录的用户与认证的信息组成的 tuple
                    # 该方法被try包裹,代表该方法会抛异常,抛异常就代表认证失败
                    user_auth_tuple = authenticator.authenticate(self)  # 注意这个self是request对象
                except exceptions.APIException:
                    self._not_authenticated()
                    raise
                # 返回值的处理
                if user_auth_tuple is not None:
                    self._authenticator = authenticator
                    # 如果有返回值,就将用户 与 登录认证 分别保存到 request.user  request.auth
                    self.user, self.auth = user_auth_tuple
                    return
            #
     如果返回值user_auth_tuple为空,代表认证通过,但是没有 登录用户 与登录认证信息,代表游客
            self._not_authenticated()

    图解

    权限的源码

     # APIView --->dispatch ---> initial ---> self.perform_authentication(request)(APIView的对象方法)
        def check_permissions(self, request):
            """
            Check if the request should be permitted.
            Raises an appropriate exception if the request is not permitted.
            """
            # 遍历权限对象列表得到一个个权限对象(权限器),进行权限认证
            for permission in self.get_permissions():
                # 权限类一定有一个has_permission权限方法,用来做权限认证的
                # 参数:权限对象self、请求对象request、视图类对象
                # 返回值:有权限返回True,无权限返回False
                if not permission.has_permission(request, self):
                    self.permission_denied(
                        request,
                        message=getattr(permission, 'message', None),
                        code=getattr(permission, 'code', None)
                    )

    图解

  • 相关阅读:
    COJ979 WZJ的数据结构(负二十一)
    COJ980 WZJ的数据结构(负二十)
    奇怪的错误
    COJ883 工艺品
    COJ885 LCS???
    COJ559 回文
    hdu1505(dp求最大子矩阵)
    hdu1506(dp求最大子矩阵)
    hdu2569(递推dp)
    hdu1081(最大子矩阵)
  • 原文地址:https://www.cnblogs.com/ZhZhang12138/p/14897124.html
Copyright © 2020-2023  润新知