前言
这段时间准备开始阅读和熟悉一下django的源码,达到更好地了解django项目,方便未来开发django 项目的目的,针对django版本号2.2.5。这一部分主要是基于django中常用的两种视图FBV和CBV的用法,了解它们实现的原理和共通的地方。
注:源代码中两个井号"##"表示我自己的注解。
本次专题——django中的FBV & CBV
我们都知道,django中的视图函数(处理业务逻辑的函数)分为两种:基于函数的视图(funtion based view, FBV)和基于类的视图(class based view, CBV)。
现有的大多数教程都会比较好地说明这两种视图的用法和使用场景,所以这里简单带过。
用法:
FBV的使用方法很简单,就是在views.py文件中写下对应的视图函数,然后在urls.py文件中写下从url到对应视图函数的映射,具体如下:
## django project: views.py
CBV的使用方法类似,在views.py中创建一个视图类xxxView,然后把视图逻辑写在对应请求方法名字的函数中,然后也是在urls.py文件中通过xxxView.as_view()函数完成将同一个url下的系列操作绑定到一个视图类并实现动态的视图函数映射,具体如下:
## django project: views.py
效果:
![deb304281054c058c155da753cf080cd.png](https://i-blog.csdnimg.cn/blog_migrate/0005fb78146da9eb02a9b562819faa5d.png)
使用场景:从上面的例子可以看出,FBV一般用于比较简单的情况,一个url对应于一个视图,这种写起来比较简单,但是组织性就会比较差;CBV则相反,一个url基于不同的请求方法可以对应到不同的视图,这样就非常方便将相似的业务逻辑组织到同一个视图类中,组织性强。个人的使用经验是:小型项目和零散的业务需求可以用FVB,大型项目和整体的业务需求更多用CVB,而且CVB还很好地在DRF(django rest framework)中得到拓展。总之,了解CBV的使用和原理对于学习django可以说是必不可少的。
源代码&分析
对于FBV的执行流程是很容易理解的,一个url对应于一个视图函数,服务器接收到对应url的请求就执行对应的视图函数并返回结果。而对于CBV的执行流程,刚开始学习使用的时候会有以下疑惑:为什么通过xxxView.as_view()就可以自动地将不同的请求方法对应到视图类中不同的视图函数,为什么视图类中的函数需要用请求方法来命名才能对应到,这些的背后实现是怎样的。
- xxxView.as_view(): 为了解答上面的疑惑,我们自然从xxxView.as_view()函数下手,但是,我们自己的实现中并没有写这个函数,所以需要从继承的原生View类中寻找,下面是源代码。
## django package: django/views/generic/base.py
- dispatch(): 从上文可见,xxxView.as_view()的结果其实就是dispatch函数的调用结果,而且从名字也可以看出,dispatch是用于在同一个url中将不同的请求方法分发给视图类中对应的函数,下面是源码。
## django package: django/views/generic/base.py
从这段源码中,可以很好地解答我们上面的疑惑,整个分发的过程其实就是根据请求方法映射同名视图函数的过程。因为我们继承了View类,并在子类(xxxView)中编写了不同请求方法的函数(get/post等),这些函数会被当作是xxxView这个视图类的实例的属性,通过request中的请求方法和内置的getattr函数被获取到,作为handler。所以,xxxView.as_view()才能正确地根据请求方法进行映射,且我们在编写时候视图函数才需要跟请求方法同名。拿到了handler之后,剩下的就是执行对应的函数并返回结果,这个就跟FBV其实是一样的了。
总结
到这里,对于FBV和CBV的使用方法、使用场景和为什么它们能被django同时支持估计算是解释得差不多了。对于本人之前在知道使用方法不知道背后原理所产生的两个疑惑:请求方法和视图类函数如何映射、视图类函数名为何只能是请求方法名,上面的源码分析也得到了解答,本人自己还是有所收获的,至少知道为啥是这么使用的。
在上面的介绍中也提到了,DRF框架中有基于CBV的扩展实现,让整个用法更加灵活,这个将在下一次文章中分享。
如果分析得不对,欢迎指正;如果对django源码有兴趣,欢迎关注投稿;如果看到这里了,不妨一赞关注三连。