Django视图中的CBV与FBV
FBV(function base views): 基于函数的视图,以函数的形式编写并处理请求。
CBV(class base views) :基于类的视图,以类的形式编写并处理请求。
FBV
FBV是目前Django主流的视图方法,首先观察以下示例代码:
urlpatterns = [
path("login/", views.login),
]
def login(request):
if request.method == 'GET':
return HttpResponse("GET方法")
if request.method == 'POST':
return HttpResponse('POST方法')
return HttpResponse('其他方法')
通过以上代码发现,FBV是通过request.method判断用户发送过来的请求方法,进而编写对应方法的业务代码。
CBV
CBV使用类来处理用户的请求,不同的请求可以在类中使用不同的方法来处理,提高了代码的可读性,常见于前后端分离项目。下面观察CBV示例代码:
urlpatterns = [
path("login/", views.Login.as_view()),
]
# CBV定义的类需要继承父类View
from django.views import View
class Login(View):
def get(self,request):
return HttpResponse("GET登录")
def post(self,request):
return HttpResponse('POST登录')
我们知道Django的URL是将一个请求分配给对应的可调用的函数的,而不是一个类,那CBV是如何实现的呢?下面来研究一下父类View的源码:
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
# logger代码略......
def view(request, *args, **kwargs):
self = cls(**initkwargs)
self.setup(request, *args, **kwargs)
# logger代码略......
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
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)
通过源码我们进一步的理解CBV 实现原理:
它首先是提供了一个静态方法as_view(),这是一个基于类的外部接口,它会返回一个视图函数,调用后会将请求传递给dispatch方法,dispatch方法通过request.method.lower()判断请求方法是否有效,然后通过反射,根据不同请求调用相应的get()或post()等方法进行处理。
大概流程就是由 path 路由的 as_view() 创建一个类的实例由此关联到类视图,关联到类视图之后,通过 CBV 内部的 dispatch() 方法进行请求的分发处理,处理完成后并将 Response 返回。
总结
CBV 体现了 Python 面向对象这一语言特性。CBV 是通过类的方式来编写视图函数,这相比较于FBV,更能利用面向对象中多态的特性,因此更容易将项目中比较通用的功能抽象出来。但本质上,FBV和CBV的处理逻辑是一摸一样的。