前言:Django的视图处理方式有两种:
- FBV(function base views) 是在视图里基于函数形式处理请求。
- CBV(class base views)是在视图里基于类的形式处理请求。
Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:
- 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
- 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性
那下面我们来看一下django的源码,从而进一步了解Django的CBV
一、首先看url:
url:
url(r'register/$',views.Register.as_view())
django的CBV在url中的书写需要在view.类名后加.as_view(),从中可以了解到as_view一定是一个方法,这个方法加上了(),是在Django项目启动时就自动执行的,返回值也应该是 一个函数名,从而在匹配url后可以执行相应的函数
PS:关于分析源码的首要任务是需要清楚方法的调用者和self的归属类!!!很重要
view.py:
class Register(View):
def get(self,request):
return render(request, 'register.html')
源码:
@classonlymethod
def as_view(cls, **initkwargs):
pass
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)
return view
源码执行简易流程图:
1.png
到此可以很明显的看出,Django项目启动后,CBV下的url执行后相当于:
url(r'register/$',views.Register.view)
二、接下来当有用户访问url时,对应url的view会执行对应请求方式下的类方法
源码:以下源码注意两点 1. cls涉及到了----《闭包作用域 》; 2. self的指向
@classonlymethod
def as_view(cls, **initkwargs):
pass
def view(request, *args, **kwargs):
self = cls(**initkwargs) //cls是Register类,self是实例化的对象
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)
return view
view.py: 找dispatch方法时需要先找自己类中,没有再找继承类中
class Register(View):
def get(self,request):
return render(request, 'register.html'))
源码: 执行对应的dispatch方法
def dispatch(self, request, *args, **kwargs):
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)
7.png