Loading

Django CBV流程及源码分析

       Django 实现视图的方法有两种,一种是FBV(function base view)即基于函数的视图,还一种高级的就是CBV(class base view),通过阅读源码你会发现它本质上还是基于FBV的。FBV的优点是用法和写法都比较简单适合刚开始学的同学使用,缺点就是不能用的面向对象的几大特性只用函数进行封装代码多的时候会显得代码很冗余,而CBV就很好的解决了这些问题。并且Django官方在后面的Django版本中加入了很多基于CBV的类,方便我们快速开发。我们先简单的看下Django在中路由规则的是怎么定义的,再粗略的看下一FBV,然后再讲下我们今天的重点CBV。

  1、Django中路由规则的定义,没有仔细读源码,简单的讲一下

    从这里进入url的定义:

      

   这是源码

      

   从源码可以看出,我们在定义路由规则时,第一个参数应该传入一个正则表达式,第二个参数传入的就是view,从下面的处理逻辑看,view的类型可以用两种。第一种是list 或tuple但这种是用来处理include(......)导入的url的,第二种类型就是callable类型的也就是可执行的即函数所以我们在写FBV的时候一定不要写上带上括号,因为url()函数需要的是一个可执行对象。如果传入这两种以外的类型就会报错。我们知道其实include导入 的其实也是一个callable类型的。所以我们可以确定view本质上传入的是一个可执行的对象,在启动服务时程序读取路由将view函数载入内存,接受到请求的时候就会执行这view函数并且返回数据。理解这一点很重要,这个是FBV和CBV的基础。  

  2、FBV中视图的定义和url的写法

   FBV(基于函数的视图),定义一个函数根据请求方法的不同而作出相应的处理,注意重点是将对请求的处理封装在一个函数中。看下例子

   view.py

   

   定义了一个login函数通过判断请求的方法进行返回

   url.py

        

   将app01中的views文件导入并将login方法传给url实现了一个FBV

   3、CBV中视图的定义和url的写法

   CBV(基于类的视图),定义一个类,继承django.views.View,将处理各种请求方式的逻辑用方法名加处理逻辑封装在方法里面,注意重点是将请求的处理封装在类里面

    eg:

           form dajngo.views import VIew

           class Cbv(View):

                  def a(self, params):
        pass

                  def b(self, params):

                        pass

      def get(self, request, *args, **kwargs):

        pass

                  def post(self, request, *args, **kwargs):

        pass

      def put(self, request, *args, **kwargs):

        pass       

   看下例子:

    view.py  视图的定义

      

   url.py  路由的写法

      

  4、分析3中的调用过程

在Django项目启动时路由规则开始载入内存当程序读到url(r'^cbv/', views.Cbv.as_View())时重点来了,views.Cbv是我们自己定义的一个对象当我们.as_view()的时候就执行了父类的静态函数as_view方法(根据面向对象的特性可以知道是调用的父类的),我们可以根据在1中得出的结论.as_view()返回的一定是个可调用对象

看下源码中as_view函数的定义:

  

可以看到,as_view方法正如我们想的那样返回的是个可调用对象view,在路由规则载入内存后.as_view的到的其实是个view方法,在接受到请求是才会执行view方法,而view方法的返回值是self.dispatch(request, *args, **kwargs),是由一个实例对象调用的dispatch方法,我们怎么这个self是谁呢?我们可以一层一层的往上拔从而确定这个实例对象是谁。

self.dispatch(request, *args, **kwargs)是由view()方法调用的,view()方法又是由as_view()方法调用的,as_view()方法又是由views.Cbv调用的,所以我们可以确定self就是Cbv的实例对象,但我们没有定义dispatch方法所以这个dispatch方法一定在Views类中有定义。

  

这就是父类中dispatch的定义,先判断请求是否正确,以get请求为例如果请求正确的话就就利用反射到self中去找与请求方式相对应的方法,根据我们上面的分析self就是我们定义的类Cbv,handler就是我们定义的get方法最后return 我们定义的get方法的返回值。一层一层的向上冒泡,get方法将返回值给dispatch,dispatchs再将返回值给view,到了view这层就和FBV一样了。

 

 

 

 

    

 


     

 

 

   

  

posted @ 2018-12-02 01:16  Just-Like  阅读(735)  评论(0编辑  收藏  举报