CBV

一、CBV与FBV

#Class Base View(基于类的视图)
#Function Base View(基于函数的视图)


二、CBV的用法及源码分析

1、用法

#视图层
# 1 先导入View(继承它)
from django.views import View
# 写一个类继承它,
class Test(View):
     #request必须传,后面的可传可不传(有可能有名,无名分组)
    def get(self, request, *args, **kwargs):
        print('get')
        return render(request, 'login.html')
    def post(self, request):
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        if name == 'pdun' and pwd == '123':
            return HttpResponse('登录成功')
        else:
            return render(request, 'login.html', {'error': '用户名或密码错误'})

#路由层
urlpatterns = [
    # as_view一定要加括号,as_view()哪里来的?  从View中继承过来的
    # as_view用类来调用的,它是一个类方法
    # 猜:as_view这个方法执行完成以后,应该是个函数的内存地址
    # 如果是get请求,会响应到类内部,执行get方法post请求,一样
    # as_view 类方法,自动把自己传过来
    url(r'^login/', views.Test.as_view()),


#模板层与FBV相同
<body>
<form action="" method="post">
    <p>用户名: <input type="text" name="name"></p>
    <p>密码: <input type="password" name="pwd"></p>
    <p><input type="submit" value="提交">{{ error }}</p>
</form>
</body>
View Code

2、源码分析

#View类中有1个数据属性,6个方法属性

class View(object):
    http_method_names = ['get', 'post', ' 'trace'。。。]

    def __init__(self, **kwargs):

    @classonlymethod
    def as_view(cls, **initkwargs): 
            def view(request, *args, **kwargs):
    
    def dispatch(self, request, *args, **kwargs):

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

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

    def _allowed_methods(self):
路由层as_view
#调用顺序: 请求来了---->as_view --> view --> dispatch----->分发到不同的函数(自己写的类中的get,post)
    可以看出as_view实际上是一个闭包,他的作用就是做一些检验工作,再返回view方法
    而view方法的作用是给请求对象补充三个参数,并调用dispatch方法处理
    dispatch方法查找到指定的请求方法,并执行相应代码块
#可以得出结论:as_view方法实际上最后就是要调用dispatch方法
#路由
    url(r'^login/', views.Login.as_view()),
class View(object):
     http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    @classonlymethod
    def as_view(cls, **initkwargs):

        def view(request, *args, **kwargs):    #这是一个闭包函数
            self = cls(**initkwargs)

              #判断self类中是不是有该(get)方法 
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request     #这几个是赋值
            self.args = args
            self.kwargs = kwargs

             #最后执行的是dispatch方法,自己的类中一般不重写这个方法,所以执行view的中的该方法
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs
        return view

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

                #request.method 前台请求的方法,转成了小写并判断在不在列表中
        if request.method.lower() in self.http_method_names:

                         #getattr的第三个参数是默认值:self.http_method_not_allowed
            #拿到get方法的内存地址
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)    
View Code
#闭包函数,内部函数包含外部函数的名称空间
def bar():
    x=8
    y=8
    def inner():
        q=x+y
        print(q)
    inner.x=1          #注意这里,不是更改X
    print(inner.__dict__)
    return inner
bar()()


{'x': 1}
16
辅助源码理解
#读源码总结

#CBV:基于类的视图
#导入from django.views import View
#自定义类继承View

#自定义的类中只能是如下方法:
    #http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    #请求流程:as_view() 的返回值是他内部view函数的内存地址
    #dispatch方法,总的分发方法
    #补充:装饰器的装饰方法
        url(r'^test/', csrf_exempt(views.test)),
        
#总结:
#路由配置好,项目启动:as_view()---->返回结果是一个函数的内存地址
#请求来了---->触发函数的执行,就会执行dispatch方法---->根据请求的不同,分发到不同的视图函数
原文地址:https://www.cnblogs.com/pdun/p/10872430.html