FBV与CBV CBV源码分析
FBV(Function Based View) 基于函数的视图
基于函数的视图,我们一直在用没啥好讲的,就是导入模块调用函数执行业务
CBV(Class Based View) 基于类的视图
路由
from app01 import views url(r'^haha/',views.zx_view.as_view()),
视图
class zx_view(View): def get(self,request): return render(request,'edit.html') def post(self,request): return HttpResponse("你好我是POST")
CBV源码分析
首先我们的路由竟然是一个函数(),这样的话是直接执行的,我们找到返回值就行
url(r'^haha/',views.zx_view.as_view()),
进入源码
@classonlymethod def as_view(cls, **initkwargs): """ Main entry point for a request-response process. """ #views.zx_view.as_view(),我们调用的时候并没有传递关键字参数,所以这个for可以跳过 for key in initkwargs: if key in cls.http_method_names: raise TypeError("You tried to pass in the %s method name as a " "keyword argument to %s(). Don't do that." % (key, cls.__name__)) if not hasattr(cls, key): raise TypeError("%s() received an invalid keyword %r. as_view " "only accepts arguments that are already " "attributes of the class." % (cls.__name__, key)) #这里有个函数但是并没有执行 def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) #这里在给函数对象添加属性 view.view_class = cls view.view_initkwargs = initkwargs #下面的代码有注释,可以知道大概的功能 #从类中获取名称和文档字符串 # take name and docstring from class update_wrapper(view, cls, updated=()) # and possible attributes set by decorators # like csrf_exempt from dispatch # 设置CSRF的装饰器 update_wrapper(view, cls.dispatch, assigned=()) #最后把函数对象给返回去了 return view
路由就相当于是这个了
那么就和FBV一样了,路由触发函数的执行
url(r'^haha/',view),
触发路由查看view是怎么执行的
def view(request, *args, **kwargs): #这个self是什么,就是我们之前创建的zx_view类对象,这里直接实例化了一个self对象 self = cls(**initkwargs) #通过反射获取get方法并且没有head方法 if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get #给self对象添加属性 self.request = request self.args = args self.kwargs = kwargs #最后执行self.dispatch(request, *args, **kwargs) return self.dispatch(request, *args, **kwargs)
self.dispatch我们知道我们的zx_view是没有这个方法的,那么就去它的父类找dispatch这个方法,结果找到了
def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, # defer to the error handler. Also defer to the error handler if the # request method isn't on the approved list. #获取请求方法并转换成小写,判断是否在http_method_names,http_method_names信息下面那段代码 if request.method.lower() in self.http_method_names: #通过反射拿到zx_view的请求的方法 handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed #执行zx_view的get或者post函数对象,并返回结果,结束 return handler(request, *args, **kwargs)
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']