CBV:基于类的视图
Django中视图函数并不一定就是函数,也可以是类。
什么!你想问什么是类!?
CBV的基本写法
from django.views import View
class Login(View):
def get(self, request):
return render(request, 'login.html')
def post(self, request):
return HttpResponse('我是类里面的post方法')
url(r'^login/', views.Login.as_view())
当我们朝login提交get请求时,会执行Login中的get方法,而朝login提交post请求时会执行其中的post方法。
那么到底为什么Login会针对不同的请求自动执行对应的方法呢?
我们通过对路由来分析
url(r'^login/', views.Login.as_view())
从路由表面应该不难看出,Login可能是通过了as_view()这个方法实现了它的全自动分拣功能!
这里as_view()这个方法应该有两种可能:
1. as_view()可能是类里面定义的普通方法staticmethod,
2. as_view()可能是类里面定义的绑定给类的方法classmethod。
让我们来瞜一眼源码~~~
@classonlymethod
def as_view(cls, **initkwargs):
果然他是classmethod
接下来我们来看一下他到底是怎么实现的呢?
as_view
"""
通过以下方法return的内容,我们首先得出一个结论
url(r'^login/', views.Login.as_view()) 等价于 url(r'^login/', views.view)
而当发生请求时,首先执行的时as_view方法
"""
@classonlymethod
def as_view(cls, **initkwargs):
pass
def view(request, *args, **kwargs):
# cls是我们自己写的Login类,产生的self对象就是Login(**initkwargs)
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
"""
这里的self使我们创建的Login产生的对象,根据对象查找属性和方法的顺序
首先找对象自己,如果没有再到自己的类中查找,自己的类中没有再查找父类的名称空间中的dispatch方法
"""
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
update_wrapper(view, cls, updated=())
update_wrapper(view, cls.dispatch, assigned=())
return view
整个cbv的精髓都在下面这几句代码中
dispatch
def dispatch(self, request, *args, **kwargs):
# 判断当前请求是否符合http_method_names中默认的八个请求方式
if request.method.lower() in self.http_method_names:
# handler = getattr(我们自己写的类产生的对象,'get', 报错信息)(以get为例,post同理)
# handeler就是通过反射获得的自己类里面的get方法
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
# 返回报错信息
handler = self.http_method_not_allowed
# 调用类里面的get方法
return handler(request, *args, **kwargs)
这样就实现了该方法的全天候全自动筛检功能!