什么是FBV和CBV?

在早期,视图开发的过程中存在一些常见的语法和模式,于是引入基于函数的通用视图来抽象这些模式,并简化了常见情况下的视图开发。因此,刚开始的时候只有FBV,而Django所做的事情就是向你定义的视图函数传递一个HttpRequest,并且希望返回一个HttpResponse。但是,基于函数的通用视图是有问题的,问题在于它很好地覆盖了简单的情况,但针对稍微复杂的场景,它没有办法在某些配置项之外进行扩展或自定义,从而极大地限制了它在许多实际应用程序中的实用性。而考虑到扩展性与自定义,这正是面向对象技术的强大之处,于是诞生了CBV。

基于类的通用视图与基于函数的通用视图目的都一样,都是为了让视图开发更加容易。但是CBV的解决方案是通过使用mixins,并且django内置了一系列通用视图作为工具集提供给我们继承使用,从而使得基于类的通用视图比基于函数的通用视图更具扩展性和灵活性。Django View视图是可调用的,用来处理请求(request)并且返回响应(response),Django的视图有两种形式:FBV和CBV。那么,什么是FBV和CBV编程模式呢?下面我们就一起通过实例来看看。

我们知道 Python 是一个门面向对象的编程语言。如果我们只用函数来编写视图函数,那么就会造成很多面向对象的优点无法利用起来,比如说封装、继承、多态等。这也是 Django 之所以加入了 CBV 模式的原因。它可以让开发者使用类的形式去编写 View 视图函数。对于使用 CBV 模式优势总结了如下几点:

  • CBV 将整个视图函数的逻辑拆成了类下的多个函数,依靠函数调用来实现完整的逻辑;

  • 提高代码的可复用性,更加灵活,让开发者使用面向对象的技术,比如多继承、多态等;

  • 可以用不同的函数针对不同的 HTTP 方法处理,而不是通过很多 if 判断,提高代码可读性。

当然 CBV 也不是万能的,当继承关系变得很复杂,亦或是代码不是特别规整的时候,这时要去找某一个函数到底是被哪一个父类重载也是一个麻烦事。此时使用 FBV 模式就变的很方便,所以还是要理解它们两者的区别,在合适的场景选用合适的方法,不能把其中某一种模式视为唯一。总体上来说 CBV 的模式,在实际的开发工作中使用的相对较多,所以我们要掌握这种编写 view 视图函数的模式。

FBV(基于函数的视图)

FBV(function based views),即基于函数的视图;CBV(class based views);也是基于对象的视图。说白了就是在每一个views中添加自己专用的方法。FBV 简单易懂,但是难以复用。它们不能像 CBV 那样能从父类中继承。FBV 的编写指南要求我们:视图代码越少越好;视图代码不能重复;视图应该只处理呈现逻辑。业务逻辑应尽可能放在数据模型中,或者表单对象中;视图代码要保持简单;使用它们来编写自定义的 403, 404, 500 等错误处理器;避免使用嵌套的 if 块。CBV是View类的集成类;这里的主要区别在于请求是以HTTP方法命名的类方法内处理的,例如GET ,POST ,PUT ,HEAD等。所以,在这里,我们不需要做一个条件来判断请求是一个 POST 还是它是一个 GET 。代码会直接跳转到正确的方法中,在 View 类中内部处理了这个逻辑。

我们首先在Django项目的URL中添加如下内容urls.py:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/$', account.login),
]

添加完成之后我们通过FBV来写一个简单的Login登录模块(views.py):

# 登录验证
def login(request):
    message = ""

    if request.method == "POST":
        user = request.POST.get('username')
        pwd = request.POST.get('password')
        c = Administrator.objects.filter(username=user, password=pwd).count()
        if c:
            request.session['is_login'] = True
            request.session['username'] = user
            return redirect('/index.html')
        else:
            message = "用户名或密码错误"

    return render(request, 'login.html', {'msg': message})

简单讲,FBV就是在views.py文件中定义函数来处理用户请求,函数中再定义如果是GET请求怎么处理,POST请求怎么处理,等等!

CBV(基于类的视图)

CBV是基于类的视图,就是使用了类来处理用户的请求,不同的请求我们可以在类中使用不同方法来处理,这样大大的提高了代码的可读性。CBV允许我们使用不同的实例方法来响应不同的HTTP请求方法,而不是像FBV那样使用条件分支代码。但是定义的类要继承父类View,所以我们在使用CBV的时候需要提前引入库:from django.views import View

执行对应请求的方法前会优先执行 dispatch 方法(在get/post/put…方法前执行),dispatch() 方法会根据请求的不同调用相应的方法来处理。其实,在我们前面学到的知识都知道 Django 的 url 是将一个请求分配给可调用的函数的,而不是一个类,那是如何实现基于类的视图的呢? 主要还是通过父类 View 提供的一个静态方法 as_view() ,as_view 方法是基于类的外部接口, 他返回一个视图函数,调用后请求会传递给 dispatch 方法,dispatch 方法再根据不同请求来处理不同的方法。

我们首先在Django项目的URL中添加如下内容urls.py:

urlpatterns = [
    path("login/", views.Login.as_view()),
]

添加完成之后我们通过CBV来写一个简单的GET和POST方法(views.py):

from django.shortcuts import render,HttpResponse
from django.views import View

class Login(View):
    def get(self,request):
        return HttpResponse("GET 方法")

    def post(self,request):
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        if user == "runoob" and pwd == "123456":
            return HttpResponse("POST 方法")
        else:
            return HttpResponse("POST 方法 1")

CBV 体现了 Python 面向对象这一语言特性。CBV 是通过类的方式来编写视图函数。这相比较于 function,更能利用面向对象中多态的特性,因此更容易将项目中比较通用的功能抽象出来。CBV 的实现原理大家可以通过看 Django 的源码就进一步的理解,大概流程就是由 path 路由的 as_view() 创建一个类的实例由此关联到类视图,关联到类视图之后,通过 CBV 内部的 dispatch() 方法进行请求的分发处理,处理完成后并将 Response 返回。

注:当我们使用CBV方式时,首先要注意urls.py文件中要写成“类名.as_view()”方式映射,其次在类中我们定义的get/post方法这些方法的名字不是我们自己定义的,而是按照固定样式,View类中支持以下方法:

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

当我们发送GET请求时,类自动将GET请求转到get方法去处理,其他请求同理!

注:

  • cbv定义类的时候必须要继承view;

  • 在写url的时候必须要加as_view;

  • 类里面使用form表单提交的话只有get和post方法;

  • 类里面使用ajax发送数据的话支持定义以下很多方法。

推荐文章

1条评论

  1. Really informative blog article. Thanks Again. Really Great. Tiffie Nathan Guenzi

发表评论

邮箱地址不会被公开。 必填项已用*标注