CBV与FBV的区别/CBV源码剖析
FBV与CBV
# 针对于视图函数(views.py),视图函数编写逻辑既可以使用函数(FBV)也可以使用类(CBV)来编写。
区别展示:
login.html
<h1>GET请求</h1><form action="" method="post" enctype="multipart/form-data"><p>username:<input type="text" name="username"></p><p>password:<input type="password" name="password"></p><input type="submit"></form>
FBV
urls.py
urlpatterns = [url(r'^loginc/',views.login),
]
views.py
def login(request):if request.method == 'POST':return HttpResponse('Post请求')return render(request,'login.html')
CBV
urls.py
urlpatterns = [url(r'^login/',views.Mylogin.as_view()) # 识别类方式
]
views.py
from django.views import View # 固定模块class Mylogin(View): # 继承Viewdef get(self,request): # 定义get方法return render(request,'login.html')def post(self,request): # 定义post方法return HttpResponse('Post请求')
总结:
FBV与CBV各有千秋CBV特点:能够直接根据请求方式的不同直接匹配到对应的方法执行
CBV源码剖析
准备工作:做一个简单的CBV来研究路由层(urls.py)
到底是怎么触发视图层(views.py)
的'类'方法的。
views.py视图层
from django.views import Viewclass MyLogin(View):def get(self,request):return render(request,'login.html') # 收到get请求走这个方法返回一个页面def post(self,request):return HttpResponse('post请求') # 收到post请求走这个返回一个'字符串'
login.html
<form action="" method="post"><input type="submit"> <!--点击提交按钮触发post请求-->
</form>
urls.py路由层
urlpatterns = [url(r'^admin/', admin.site.urls),url(r'login/',views.MyLogin.as_view())
]
那么我们如何去研究呢?
# 我们先来探讨url
url(r'login/',views.MyLogin.as_view())# 我们可以看到他与FBV的区别就在于后面所对应的 类名.as_view()我们知道在python中一切皆'对象',那么类使用(.)的方式时,类(.)的是肯定是一个属性或者一个方法
那么说明as_view()要么是一个属性要么是一个方法。
但是他加了一个(), 我们可猜测他是一个方法,他就相当于'函数名+()'# 补充: 函数名/方法名 加括号()执行优先级最高,
这就就相当于在用户访问路由后缀为login/时,就会立刻执行views下的MyLogin类下的as_view()
# 那么我们就来研究这个as_view()到底是什么样的逻辑呢。猜测:as_view() # 要么是被@staticmethod修饰的静态方法as_view() # 要么是被@classmethod修饰的类方法# 通过ctrl+左键的方式点进去看一下他的源码
@classonlymethod
def as_view(cls, **initkwargs):# 通过源码我们可以看到他确实是一个绑定给类的方法,类来调用,就把类当作第一个参数传入
我们来研究一个这个函数:
函数的返回值:view # 为内部函数的函数名
# 那么在启动django的时候就会立刻执行as_view方法,as_view的返回值为view
那么就相当于:
url(r'login/',views.MyLogin.as_view())
同等于:
url(r'^login/,views.view') # 那么这个结果是不是和FBV模式一摸一样# 通过这一点:CBV与FBV在路由匹配上本质是一样的。都为(路由,views.函数内存地址)
那么在用户输入路由后缀为login/的时候就会自动触发view方法。
那么我们来研究view方法:
def view(request, *args, **kwargs):self = cls(**initkwargs) # cls为我们自己写的类(MyLogin) 加括号后产生对象# 相当于:self = MyLogin(**initkwargs) # 类加()就产生一个我们自己写的类的对象selfif hasattr(self, 'get') and not hasattr(self, 'head'): # 反射self.head = self.getself.request = request # 这里是给对象赋值一些属性self.args = argsself.kwargs = kwargsreturn self.dispatch(request, *args, **kwargs)# 对象.一个属性 :查找属性的顺序:先去对象自己找,再去产生对象的类里面找,之后再去父类里找# 一定要明白当前的self是谁。(这里self为我们自己写的类产生的对象)# 那么这里没有dispatch方法 ,我们自己写得类里面也没有,那么就去类继承得父类View查看有没有该方法# 那么我们就去找一下这个dispatch属性/方法
研究:View: dispatch
# 很明显在上述的view方法里没有,我们自己写的MyLogin类里肯定也是没有的,那么我们就来研究视图层:我们所编写的类所继承的(View)
class MyLogin(View): # 同样通过ctrl+鼠标左键的方式点进去看一下
# 我们来研究一下这个代码 def dispatch(self, request, *args, **kwargs):# 获取当前请求方式并转为小写 然后比对当前比对是否合法(这里就以'GET'请求为例)if request.method.lower() in self.http_method_names:handler = getattr(self, request.method.lower(), self.http_method_not_allowed)# getattr反射:通过字符串来操作对象的属性或者方法(那么第二个参数位置即为'get')如果'get'方法有值就返回get方法得返回值,我们在定义类得时候,定义了get方法的,所有就会返回get方法得返回值# 括号内参数解释:(self:自己写的类产生的对象,'get',当找不到get方法的时候就会找第三个参数)# 那么现在就相当于:# handler = getattr(我们自己写的类产生的对象,'get','当找不到get属性或者方法就会用第三个参数返回该参数对应方法得返回值')# get如果存在:hanler就相当于:handler = 我们自己写的get方法else:handler = self.http_method_not_allowed # 找不到get方法走的方法(抛出异常)return handler(request, *args, **kwargs) # 自动调用我们自己写的get方法# 那么post方法同理
这样就疏通了CBV的执行流程。其实内部还是FBV
CBV与FBV的区别/CBV源码剖析相关推荐
- SpringDataJPA+Hibernate框架源码剖析(六)@PersistenceContext和@Autowired注入EntityManager的区别
SpringDataJPA+Hibernate框架源码剖析系列文章: SpringDataJPA+Hibernate框架源码剖析(一)框架介绍 SpringDataJPA+Hibernate框架源码剖 ...
- 源码剖析Django REST framework的认证方式及自定义认证
源码剖析Django REST framework的认证方式 由Django的CBV模式流程,可以知道在url匹配完成后,会执行自定义的类中的as_view方法. 如果自定义的类中没有定义as_vie ...
- Kafka源码剖析 —— 网络I/O篇 —— 浅析KafkaSelector
为什么80%的码农都做不了架构师?>>> ##NioSelector和KafkaSelector有什么区别? 先说结论,KafkaSelector(org.apache.kaf ...
- Mongoose源码剖析:外篇之web服务器
引言 在深入Mongoose源码剖析之前,我们应该清楚web服务器是什么?它提供什么服务?怎样提供服务?使用什么协议?客户端如何唯一标识web服务器的资源?下面我们抛开Mongoose,来介绍一个we ...
- 一个完整的python项目源码-一个Python开源项目-腾讯哈勃沙箱源码剖析(上)
前言 2019年来了,2020年还会远吗? 请把下一年的年终奖发一下,谢谢... 回顾逝去的2018年,最大的改变是从一名学生变成了一位工作者,不敢说自己多么的职业化,但是正在努力往那个方向走. 以前 ...
- boost源码剖析之:泛型函数指针类boost::function(rev#3)
boost源码剖析之:泛型函数指针类boost::function(rev#3) 刘未鹏 C++的罗浮宫(http://blog.csdn.net/pongba) Note: 并非新作,03年曾放 ...
- boost源码剖析之:泛型编程精灵type_traits(rev#2)
boost源码剖析之:泛型编程精灵type_traits(rev#2) 刘未鹏 C++的罗浮宫(http://blog.csdn.net/pongba) 动机 使用traits的动机一般有三种,分派. ...
- python的对象模型_[ Python 源码剖析] 对象模型概述
Python 是一门 面向对象 语言,实现了一个完整的面向对象体系,简洁而优雅. 与其他面向对象编程语言相比, Python 有自己独特的一面. 这让很多开发人员在学习 Python 时,多少有些无所 ...
- Zookeeper--Watcher机制源码剖析一
Watcher-- 数据变更通知 我们知道Zookeeper提供来分布式数据的订阅/发布功能,一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能让多个订阅者同时监听某个主题对象,当这个被监听对 ...
最新文章
- ASP.NET MVC扩展库
- 第三天2017/03/30(上午:二级指针的(输入)内存模型:(共三种模型))
- javascript 打造城市选择控件,兼容IE6以及以上,谷歌,Firefox
- JavaScript之eval() 函数
- 上交AI研究院副院长马利庄:基于大数据的人脸识别技术进展与展望
- 浅学一下XMind思维导图
- 大数据笔记--Spark机器学习(第二篇)
- jxls遍历list时使用模板的批注语法
- 从零开始设计RISC-V处理器——指令系统
- Ubuntu配置adb
- 第二届天府大地艺术季(春)三道堰青杠树村分会场开幕
- OIer__ZLY__OI计划
- Python使用PyAudio制作录音工具
- 2021极术通讯-CSL-YOLO | 超越Tiny-YOLO V4,全新设计轻量化YOLO模型实现边缘实时检测
- 三星T7装Linux系统,Ubuntu已成为三星ARTIK 5/7的主力GNU/Linux系统
- 文本代码编辑器UltraEdit v26.00.0.74 中文版下载与破解方法【亲测有效】
- 跟着别人学学优化自己的Ubuntu 操作系统
- oracle ORA-28000: the account is locked 28000. 00000
- 仿某鸟云前台 智简魔方IDC财务管理系统
- Baltur两级燃气燃烧器BTG 3,6 P 50-60Hz
热门文章
- html flex 兼容ie9,flex布局及其兼容解决方案_蓝戒的博客
- 基本数据类型与构造数据类型
- 多多客api_多多进宝API功能更新公告
- 薅羊毛之讯飞输入法助我生成字幕文件
- linux 系统调用 优先级,Linux内核学习笔记(6)-- 进程优先级详解(prio、static_prio、normal_prio、rt_priority)...
- 网络技能大赛-2019年国赛真题[2019年全国职业技能大赛高职组计算机网络应用赛项真题-H卷]AC/AP/EG部分答案详解
- python速度_只需一行代码,让你的Python运算速度更加流畅!
- dell电脑EliteBook开启虚拟化
- 宁波SEO营销,如何更新网站文章?
- 笔记:Cannot resolve :xxxx :2.1.0.M4