CBV_____dispatch()

django视图一般分为FBV和CBV,这里主要介绍CBV的主要流程

CBV的逻辑流程为

1.url--执行 as_view()

2.as_view()返回view()

3.view() 返回 dispatch()

也就是说,所有的请求最后都是通过dispatch()处理的,下面举例说明dispatch是如何工作的

 

1.父类的dispatch理解

urls代码:

from django.urls import path
from . import views
urlpatterns = [
    path('cbv/',views.CbvView.as_view()),
]

views代码:

from django.http import HttpResponse
from django.views import View
class CbvView(View):
    def get(self,request,*args,**kwargs):
        return HttpResponse('cbv的get请求')
    def post(self,request,*args,**kwargs):
        return HttpResponse('cbv的post请求')

前面已经整理到CBV的逻辑流程,最后都是执行的dispatch方法,这里贴下dispatch源码:

def dispatch(self, request, *args, **kwargs):
    #由于request.method返回的都是大写的请求类型,如GET,所以需要小写处理
    #基于反射,如果self的请求类型在http_method_names里面,则执行self的对应方法
    #如:假如请求是post方法,然后post在http_method_names里面,然后返回self(也就是CbvView)的post方法,然后根据我们定义的post方法的逻辑进行处理
    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
    return handler(request, *args, **kwargs)

测试一下情况:

当发送get请求的时候,由于request.method为GET,所以查看dispatch中的代码等同于 handler = getattr(CbvView,'get'),最后return出来的是 CbvView的get方法,如下图:

 

 

 同理,当请求为post时,如下图:

 

 

 

2.尝试重写父类的dispatch方法

在CBV类中直接重写父类的dispatch方法,这样就不会去执行父类的dispatch了

views代码修改如下:

class CbvView(View):
    def dispatch(self,request,*args,**kwargs):
        return HttpResponse('子类中重写的dispatch')
    def get(self,request,*args,**kwargs):
        return HttpResponse('cbv的get请求')
    def post(self,request,*args,**kwargs):
        return HttpResponse('cbv的post请求')

然后这时候调用不管是用get请求还是post请求,得到的返回都是 "子类中重写的dispatch"
这里再一次理下逻辑

1.路由中去执行CbvView的as_view()方法,但是CbvView类中没有这个方法,所以去父类中找

2.父类View中as_view()方法经过一系列处理之后返回的是self.dispatch()方法,这里的self指的是CbvView,所以下一步去CbvView中找dispatch方法

3.由于我们在子类CbcView中重写了disptch方法,所以执行子类的该方法,又由于我们这里直接是返回 HttpResponse('子类中重写的dispatch'),

所以不管请求是什么类型,只要请求过来,都是return的 "子类中重写的dispatch"

PS:这里重写的dispatch和源码自带的dispatch不一样,这里更好的理解源码中的dispatch ,是经过了一次请求method判断,然后根据判断的类型,handler就是反射
得到CBV类中对应的函数,(请求methdod是GET 就反射得到CbvView中的get方法)

测试如图:

 

 

 

 3.继承

用CBV写视图函数其中最大的好处就是可以试用面向对象的特性,比如对某一些视图,都需要做到某一个操作,这时候可以把这个操作封装起来,然后需要用到该操作的视图都继承于
该类,这样就不用每个视图类中取重复编码了
举例说明:
views文件修改如下:

from django.http import HttpResponse
class MyBase_View(object):
    def dispatch(self,request,*args,**kwargs):
        print('这里可以写一些公用的操作,所有继承该类的视图函数 就不用重复编码了')
        #由于所有继承该类的都是CBV视图类,会多重继承,多重继承关系中兄弟节点也是可以继承的,所以这里的dispatch会去View中继承
        ret = super(MyBase_View,self).dispatch(request,*args,**kwargs)
        return ret
           
class CbvView(MyBase_View,View):
    # def dispatch(self,request,*args,**kwargs):
    #     # return HttpResponse('子类中重写的dispatch')
    #     #这里多继承,优先MyBaseView
    #     ret=super(CbvView,self).dispatch(request, *args, **kwargs)
    #     return ret
    def get(self,request,*args,**kwargs):
        return HttpResponse('cbv的get请求')
    def post(self,request,*args,**kwargs):
        return HttpResponse('cbv的post请求')

接下来不管我们发送什么请求,控制台都会先打印MyBase_View中输出的语句,然后正常执行我们视图类中的各个请求逻辑。

如图:

 

 

 

posted @ 2020-11-13 17:25  Alantammm  阅读(123)  评论(0编辑  收藏  举报