CBV源码与APIView源码解析
一、CBV源码解析
在我们写cbv的时候在url中和fbv的区别就是是否调用了as_view()方法,所以关键入手点就是这个方法
@classonlymethod
	# 这是类的绑定方法,这个cls是我们创造的类
def as_view(cls, **initkwargs):
    def view(request, *args, **kwargs):
        # self是在实例化一个对象
        self = cls(**initkwargs)
        if hasattr(self, 'get') and not hasattr(self, 'head'):
            self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            # 关键在dispatch内
            return self.dispatch(request, *args, **kwargs)
     return view
        def dispatch(self, request, *args, **kwargs):
           # http_method_names是一个存放了所有请求方式的列表
            if request.method.lower() in self.http_method_names:
                # 用到了反射的方法吗,如果CBV中我们写了这个请求的方法,就把他赋值给handler,如果没有就返回一个not_allowed
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
                    return handler(request, *args, **kwargs)
二、APIView源码解析
apiview同样关键点在as_view中
 @classmethod
    def as_view(cls, **initkwargs):、
        # 继承了父类View的as_view的调用结果,就是父类的view
    	view = super().as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs
        # 这是调用了屏蔽csrf检测的装饰器
        return csrf_exempt(view)
   	# 这里要注意区分,return中的view,其实就是父类中的view
        def view(request, *args, **kwargs):
                # 关键还是在dispatch内
                # 注意此刻dispatch的查找顺序,定义的类中没有,去父类APIView中找,我们发现了新的dispatch方法
                return self.dispatch(request, *args, **kwargs)
# APIView的dispatch方法
    def dispatch(self, request, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        # 重新包装成一个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
            # 响应模块,调用请求函数得到一个响应对象,此时内部存放的是json数据
            response = handler(request, *args, **kwargs)
        except Exception as exc:
            # 异常模块
            response = self.handle_exception(exc)
        # 渲染模块,我们能在前端看到api的html页面,就是这里做的
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response 
    # APIView的initial方法,认证模块
 	def initial(self, request, *args, **kwargs):
        # 认证组件:校验用户 - 游客、合法用户、非法用户
        # 游客:代表校验通过,直接进入下一步校验(权限校验)
        # 合法用户:代表校验通过,将用户存储在request.user中,再进入下一步校验(权限校验)
        # 非法用户:代表校验失败,抛出异常,返回403权限异常结果
        self.perform_authentication(request)
        # 权限组件:校验用户权限 - 必须登录、所有用户、登录读写游客只读、自定义用户角色
        # 认证通过:可以进入下一步校验(频率认证)
        # 认证失败:抛出异常,返回403权限异常结果
        self.check_permissions(request)
        # 频率组件:限制视图接口被访问的频率次数 - 限制的条件(IP、id、唯一键)、频率周期时间(s、m、h)、频率的次数(3/s)
        # 没有达到限次:正常访问接口
        # 达到限次:限制时间内不能访问,限制时间达到后,可以重新访问
        self.check_throttles(request)
    # 我们再看看新赋值的request内部是什么
    def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)
        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    # 再点击Request,我们发现原来的request被封装给_request了,之后使用request都是在原来基础上新造的
    # 原来的request都是.属性的,所以我们可以很肯定这里重写了点拦截方法(__getattr__)
    def __getattr__(self, attr):
        try:
            return getattr(self._request, attr) #通过反射,取原生的request对象,取出属性或方法
        except AttributeError:
            return self.__getattribute__(attr)
APIView还给我们做了一件事情,因为我们后面在通过api进行数据交互的时候用的都是json格式的数据,但是django默认不会处理json格式的数据,所以这里他新定义的request有一个data方法
@property
def data(self):
    if not _hasattr(self, '_full_data'):
        self._load_data_and_files()
        return self._full_data
他还重新定义了GET的名字,我们本来拿到get请求来的数据应该是django.GET来的,但是由于我们是查找数据,这样的名字不够见名知意所以,
    @property
    def query_params(self):
        """
        More semantically correct name for request.GET.
        """
        return self._request.GET
用request.query_params来替代request.GET,当然由于之前重写request的时候用了反射的方法把原生request的方法属性全都赋值给了新的request所以GET也是能用的
CBV源码与APIView源码解析的更多相关文章
- CBV源码分析+APIVIew源码分析
		
{drf,resful,apiview,序列化组件,视图组件,认证组件,权限组件,频率组件,解析器,分页器,响应器,URL控制器,版本控制} 一.CBV源码分析准备工作: 新建一个Django项目 写 ...
 - Restful规范-APIView源码分析
		
目录 一.Restful规范 十条规范 二.drf的简单使用 三.APIView源码分析 CBV源码分析 APIView源码分析 一.Restful规范 Restful规范是一种web API接口的设 ...
 - DRF之APIView源码解析
		
目录 Django项目中的代码如下 APIView源码解析 源码解析总结 Django项目中的代码如下 urls.py中: from django.conf.urls import url from ...
 - $Django cbv源码分析  djangorestframework框架之APIView源码分析
		
1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...
 - DRF  cbv源码分析  restful规范10条   drf:APIView的源码 Request的源码   postman的安装和使用
		
CBV 执行流程 路由配置:url(r'^test/',views.Test.as_view()), --> 根据路由匹配,一旦成功,会执行后面函数(request) --> 本质就是执 ...
 - DRF(1) - REST、DRF(View源码解读、APIView源码解读)
		
一.REST 1.什么是编程? 数据结构和算法的结合. 2.什么是REST? 首先回顾我们曾经做过的图书管理系统,我们是这样设计url的,如下: /books/ /get_all_books/ 访问所 ...
 - REST、DRF(View源码解读、APIView源码解读)
		
一 . REST 前言 1 . 编程 : 数据结构和算法的结合 .小程序如简单的计算器,我们输入初始数据,经过计算,得到最终的数据,这个过程中,初始数据和结果数据都是数据,而计算 ...
 - Restful 1 -- REST、DRF(View源码解读、APIView源码解读)及框架实现
		
一.REST 1.什么是编程? 数据结构和算法的结合 2.什么是REST? - url用来唯一定位资源,http请求方式来区分用户行为 首先回顾我们曾经做过的图书管理系统,我们是这样设计url的,如下 ...
 - Django rest framework框架——APIview源码分析
		
一.什么是rest REST其实是一种组织Web服务的架构,而并不是我们想象的那样是实现Web服务的一种新的技术,更没有要求一定要使用HTTP.其目标是为了创建具有良好扩展性的分布式系统. 可用一句话 ...
 
随机推荐
- Python + MySQL 批量查询百度收录
			
做SEO的同学,经常会遇到几百或几千个站点,然后对于收录情况去做分析的情况 那么多余常用的一些工具在面对几千个站点需要去做收录分析的时候,那么就显得不是很合适. 在此特意分享给大家一个批量查询百度收录 ...
 - PHP源码进行加密(仅linux)
			
加密软件(php_screw) 1.下载网站:http://sourceforge.net/projects/php-screw/ 2.描述: php文件通常以文本格式存贮在服务器端, 很容易被别人读 ...
 - nginx下如何l在网站目录的二级目录下url重写的方法
			
以我新项目为例子,该项目要求用laravel来做,因此我把整个项目丢到一个叫laravel的文件夹里面了,目录就变成c:/nginx/html/laravel了,然后发现只能通过localhost/l ...
 - nsswitch名称解析框架
			
name service switch 名称解析框架(逻辑图) 让多种应用程序能灵活进行名称解析的通用框架 与各种类型存储进行交互的公共实现 规定通过哪些途径以及按照什么顺序通过这些途径来查找特定类型 ...
 - Pants On Fire(链式前向星存图、dfs)
			
Pants On Fire 传送门:链接 来源:upc9653 题目描述 Donald and Mike are the leaders of the free world and haven't ...
 - 2019-02-04  Linux的一些常用命令学习
			
今天在电脑里用装了个ubuntu的虚拟机,学习了一下基本操作 ls ls用于查看文件夹的文件 mkdir mkdir可以创建一个文件夹(directory) cd 目录切换 pwd print wor ...
 - map集合 可变对象
			
#map集合 可变对象 stu = {'xiaoming':34,'xiaohogn':56,'小王':569} print(stu['小王']) ''' 如果key不存在,dict就会报错: > ...
 - Android学习笔记基于回调的事件处理
			
流程: 常见的回调方法: 代码示例: @Override public boolean onTouchEvent(MotionEvent event) { Toast.makeText(getAppl ...
 - S7-200 PLC内部+5VDC电源的负载能力
			
S7-200 PLC内部+5VDC电源的负载能力 S7-200 CPU模块提供DC5V和24V电源:当有扩展模块时,CPU通过I/O总线为其提供5V电源,所有扩展模块的SV电源消耗之和不能超过该CPU ...
 - Spring 中Controller 获取请求参数的方法笔记
			
1.直接把表单的参数写在Controller相应的方法的形参中,适用于get方式提交,不适用于post方式提交.若"Content-Type"="application/ ...