Django的CBV和FBV

FBV

FBV ( function base views ) 就是在视图里面使用函数处理请求。

CBV

CBV ( class base views) 就是在视图中使用类处理请求。

Django 加入 CBV 之后我们可以使用类来写 View。这样做的有点是:

  • 提高了代码的复用性,可以使用面向对象的技术,例如Mixin(多继承)
  • 可以用不同的函数针对不同的 HTTP 方法处理,而不是通过很多的 if 来判断,提高了代码的可读性

使用class-based-views

使用 CBV 写GET 方法:

from django.http import HttpResponse
from django.views import View


class IndexView(View):
    def get(self, request):
        return HttpResponse("ok")

此时配置 url的时候:

# urls.py 文件中

from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.IndexView.as_view()),
]


# 其中  views.IndexView.as_view() 中的  .as_view() 是固定写法

Django 的 url 是将一个请求分配给可调用的函数,而不是一个class类。针对这个问题,CBV提供了一个个 as_view()  的静态方法(即类方法),调用这个方法会创建一个类的实例,然后通过实例调用 dispatch() 方法,dispatch() 方法会根据 request 的 method 的不同调用相应的方法来处理 request(如get(),post() 等)。之后又和FBV差不多,要接收 request , 得到一个 response 返回。如果方法没有定义,会抛出 HttpRespondeNotAllowed 异常。

类的属性可以通过两种方法进行设置:

# 第一种方法是常见的 python 方法,可以被子类覆盖。

class IndexView(View):
    name = 'xm'
    
    def get(self, request):
        return HttpResponse(self.name)

# 这种方法也可以被子类覆盖

class ChileIndexView(IndexView):
    name = 'xh'



# 第二种方法是在url中指定类的属性:

urlpatterns = [
    url(r'^index/$', views.IndexVieew.as_view(name='chenchen')), 
]

在使用CBV进行POST请求的时候会被 出现 Forbidden 错误,这是因为在启动 Django 项目的时候会自动进行 csrf 验证。

解决办法:

# 全局解决-----> 即注释掉 csrf 中间件

# 局部解决:

# 针对视图函数避免 csrf 验证
    from django.views.decorators.csrf import csrf_exempt
    @ csrf_exempt()
    def post(self, request):
        return HttpResponse("POST")

# 类方法中:
# 方法一:

from django.shortcuts import render, HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator


@method_decorator(csrf_exempt, name="dispatch")
class IndexView(View):

    def get(self, request, *args, **kwargs):
        return HttpResponse("OK")

    def post(self, request, *args, **kwargs):
        return HttpResponse("POST")

# 方法二:

from django.shortcuts import render, HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

class IndexView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        print("hello")
        # 执行父类中的dispatch方法
        ret = super(IndexView, self).dispatch(request, *args, **kwargs)
        print("boy")
        return ret

    def get(self, request, *args, **kwargs):
        return HttpResponse("OK")

    def post(self, request, *args, **kwargs):
        return HttpResponse("POST")

使用 Mixin

 首先要明白 Django 引入 CBV 的目的:

  Python 的一大重要特性就是面向对象。CBV 更能体现 python 的面向对象。CBV 是通过 class 的方式来实现视图方法的。

  class 相对于 function 来说,更能利用多态的特点,因此更容易从宏观层面上将项目内比较通用的功能抽象出来,可以理解为一个东西具有多种形态( 的特性 )。CBV 的实现原理大体就是由 url 路由到这个 CBV 之后,通过 CBV 内部的 dispatch 方法进行分发,将 get 请求分发给 cbv.get 方法处理,将 post 请求分发给 cbv.post 方法处理。

  在 Django 中使用 Mixin 来重用代码,一个 View Class 可以继承多个Mixin,但是只能继承一个 View(包括View 的子类),推荐把 View 写在最右边,多个 Mixin 写在左边。

Mixin

Mixin

  在设计类的继承关系的时候,通常主线都是单一继承下来的。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,这种设计通常称为Mixin。

  Mixin 的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个 Mixin 的功能,而不是设计多层次的复杂的继承关系。

  python 自带的很多库也使用了 Mixin。例如,Python 自带了 TCPServer 和 UDPServer 这两类网络服务,而要同时服务多个用户就必须使用多进程或多线程模型,这两种模型由 ForkingMixin 和 ThreadingMixin 提供。通过组合, 我们就可以创造出合适的服务来。

比如,编写一个多进程模式的 TCP 服务,定义如下:

class MyTCPServer(TCPServer, ForkingMixin):
    pass

编写一个多线程模式的 UDP 服务,定义如下:

class MyUDPServer(UDPServer, ThreadingMixin):
    pass

如果想要搞一个更先进的协程模型,可以编写一个 CoroutineMixin:

class MyTCPServer(TCPServer, CoroutineMixin):
    pass

这样一来,我们不需要复杂而庞大的继承链,只要选择组合不同的类的功能,就可以快速构造出所需的子类。

小结

由于 Python 允许使用多重继承,因此,Mixin 就是一种常见的设计。只允许单一继承的语言(如java)是不能使用 Mixin 的设计的。

 

posted on 2018-04-08 19:50  卖火柴的嫩火柴  阅读(138)  评论(0编辑  收藏  举报

导航