• 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的处理逻辑是一摸一样的。