一、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>
2、源码分析
class View(object):http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']@classonlymethoddef 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.getself.request = requestself.args = argsself.kwargs = kwargs#如果类中没有写dispatch,会执行View中的dispatch方法return self.dispatch(request, *args, **kwargs)view.view_class = clsview.view_initkwargs = initkwargsreturn viewdef dispatch(self, request, *args, **kwargs):#request.method 前台请求的方法,转成了小写#http_method_names View中定义的一个列表:在上边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_allowedreturn handler(request, *args, **kwargs)
#闭包函数,内部函数包含外部函数的名称空间 def bar():x=8y=8def inner():q=x+yprint(q)inner.x=1 #注意这里,不是更改Xprint(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方法---->根据请求的不同,分发到不同的视图函数



















