ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

DRF源码分析

2021-06-17 20:32:38  阅读:161  来源: 互联网

标签:分析 __ 对象 self request 认证 源码 kwargs 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)
                )

图解

 

标签:分析,__,对象,self,request,认证,源码,kwargs,DRF
来源: https://www.cnblogs.com/ZhZhang12138/p/14897124.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有