• 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中输出的语句,然后正常执行我们视图类中的各个请求逻辑。

    如图:

     

  • 相关阅读:
    Android 8.0 adb shell dumpsys activity activities | findstr mFocusedActivity 获取当前的 activity 显示空的
    spring-in-action_day01
    spring-in-action_day02
    spring-in-action-day04-配置属性 @ConfigurationProperties
    springmvc接收参数
    spring中Utils工具类注入问题
    Eclipse Push出现rejected
    Eclpis-cannot open git-receive-pack
    IO
    LinkedHashmap简要说明
  • 原文地址:https://www.cnblogs.com/alantammm/p/13970455.html
Copyright © 2020-2023  润新知