刚开始的时候,django只有基于函数的视图(Function-based views)。为了解决开发视图中繁杂的重复代码,基于函数的通用视图( Funcation-based generic views)出现了,但是不久它的弊端就显示出来:无法扩展、无法定制。基于函数的通用视图的不灵活导致它在现实世界中的应用受限。基于类的通用视图也是出于同样的目的被开发出来,它提供一个工具箱(基类)并支持多重继承,随着它的应用,人们发现它的可扩展性和灵活性远超它的小兄弟——基于函数的通用视图。

基于类的通用视图是基于函数的通用视图的质的飞跃,而不仅仅是改进。

—————————————————————————————————————————————————————————————————

使用基于类的视图

一般而言,如果要对不同的HTTP请求做出不同的相应的话,function-based views会在单一的函数中采用判断分支的方法,比如:

from django.http import HttpResponse

def my_view(request):
if request.method == 'GET':
# <view logic>
return HttpResponse('result')
if request.method == 'POST':
# <view logic>
return HttpResponse('result')

而在class-based views中,你可以用不同的类实例的方法来响应不同的HTTP request,如:

from django.http import HttpResponse
from django.views.generic.base import View class MyView(View):
def get(self, request):
# <view logic>
return HttpResponse('result')
def post(self, request):
# <view logic>
return HttpResponse('result')

django的URL解析器需要将request和相应的参数传递给一个可调用的函数,而不是一个类。所以class-based view提供一个类方法:as_view()来解决这个问题,as_view()方法让你可以把类当做函数来调用。as_view创建一个类实例,然后调用它的dispatch方法,dispatch分析出request是GET、POST或者其他,然后将request匹配给相应的函数,比如将POST请求匹配给post()函数,如果给函数没有定义的话,将引发HttpResponseNotAllowed错误。

# urls.py
from django.conf.urls import patterns
from myapp.views import MyView urlpatterns = patterns('',
(r'^about/', MyView.as_view()),
)

虽然小型的class-based view并不需要依靠类属性来完成它的工作,但是类属性在很多的基于类的设计中都很有用。设置类属性有两个方法。

第一个方法是标准的python方法:在子类中重写类的属性和方法,比如:

from django.http import HttpResponse
from django.views.generic.base import View class GreetingView(View):
greeting = "Good Day" def get(self, request):
return HttpResponse(self.greeting)

你可以在子类中这样重写:

class MorningGreetingView(GreetingView):
greeting = "Morning to ya"

第二个方法是在URLconf中将类属性作为参数传递给as_view():

urlpatterns = patterns('',
(r'^about/', GreetingView.as_view(greeting="G'day")),
)

————————————————————————————————————————————————————————————————————

使用mixins

mixin是多重继承的一种,它将父类的行为和属性结合在一起。比如说,在基于类的通用视图中,有一个mixin叫TemplateResponseMinxin,它原本的目的是定义方法render_to_response()。当与基础类View的行为结合时,结果是一个神奇的TemplateView类:它拥有分析request并作出相应匹配的方法(原本定义在View中的行为),也拥有一个接受一个template_name并返回一个TempalteReponse对象的render_to_response()方法(原本定义在 TemplateResponseMixin中的行为)

mixins是在不同的类之间重用代码的出色方法,但是它也带来了一些代价。也许你已经注意到了,如果你滥用这种方法的话,你将会迷失在mixin中,因为在冗长的继承树中,你很难辨清一个子类到底是用来干嘛的。

注意你只能从一个通用视图中继承,就是说,只能有一个父类是从View类继承来的。如果你在多个View类的子类中继承,比如尝试将ProsessFormView和ListView结合,结果将不会是你期待的那样。

————————————————————————————————————————————————————————————————————

用基于类的视图处理表格

一个基于函数的视图在处理表格时,看起来会像这样:

from django.http import HttpResponseRedirect
from django.shortcuts import render from .forms import MyForm def myview(request):
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/')
else:
form = MyForm(initial={'key': 'value'}) return render(request, 'form_template.html', {'form': form})

而相似的基于类的视图会想这样:

from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views.generic.base import View from .forms import MyForm class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html' def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form}) def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/') return render(request, self.template_name, {'form': form})

虽然只是一个简单的例子,但是你可以看到,你可以通过这样的方式来定制视图。比如通过URLconf配置重写类属性(像form_class),或者重写、继承一个或更多的方法。

——————————————————————————————————————————————————————————————————————

装饰基于类的视图

class-based view的扩展并不局限于mixins,你也可以使用装饰器。由于基于类的视图不是函数,使用as_view或者创建子类将会以不同的方式了来装饰他们:

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView from .views import VoteView urlpatterns = patterns('',
(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
)

这是装饰一个实例的方法。如果你想装饰视图的每一个实例,你需要使用另一种方法。

————————————————————————————————————————————————————————————————————————

装饰类

为了装饰基于类的视图的每一个实例,你需要装饰这个类本身。你可以将这个装饰器应用于类的dispatch()方法来达到这一目的。

类的方法和独立的方法并不完全一样,所以你不能直接将函数装饰器应用于类方法——你需要先将它转化成一个方法装饰器。method_decorator装饰器将一个函数装饰器转化成一个方法装饰器,这样一来,他就可以应用于实例的方法。例如:

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView class ProtectedView(TemplateView):
template_name = 'secret.html' @method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ProtectedView, self).dispatch(*args, **kwargs)

在这个例子中,每个ProtecedView都将有login保护。

注意,method_decorator将 *args 和 **kwargs传递给被装饰的类方法做参数。如果你的方法不接受这种参数,它将引发TypeError

Django——基于类的视图(class-based view)的更多相关文章

  1. 介绍——基于类的视图(class-based view)

    ​刚开始的时候,django只有基于函数的视图(Function-based views).为了解决开发视图中繁杂的重复代码,基于函数的通用视图( Class-based generic views) ...

  2. Django 基于类的视图(CBV)执行流程 CBV 源码分析

    一.CBV(基于类的视图) 视图是可以调用的,它接受请求并返回响应,这不仅仅是一个函数,Django提供了一些可以用作视图的类的例子,这些允许您通过继承或mixin来构建视图并重用代码. 基本示例 D ...

  3. Django——基于类的视图源码分析 一

    基于类的视图(Class-based view)是Django 1.3引入的新的视图编写方式,用于取代以前基于函数(Function-based)方式. 借助于OO和Python中方便的多重继承特性, ...

  4. Django——基于类的视图源码分析 二

    源码分析 抽象类和常用视图(base.py) 这个文件包含视图的顶级抽象类(View),基于模板的工具类(TemplateResponseMixin),模板视图(TemplateView)和重定向视图 ...

  5. python测试开发django-rest-framework-62.基于类的视图(APIView和View)

    前言 django中编辑视图views.py有两种方式,一种是基于类的实现,另外一种是函数式的实现方式,两种方法都可以用. REST框架提供了一个APIView类,它是Django View类的子类. ...

  6. Django——基于类的视图源码分析 三

    列表类通用视图(list.py) 此文件包含用于显示数据列表常用的类和工具类.不仅可以方便的用于显示基于模型(Model)的数据列表,也可以用于显示自定义数据列表. 此图中绿色部分属于base.py, ...

  7. django 中基于类的视图

    django 视图 分为两种: 1.  FBV  基于函数的视图      function   based  view 2.  CBV  基于类的视图         class   based  ...

  8. Django编写RESTful API(三):基于类的视图

    欢迎访问我的个人网站:www.comingnext.cn 前言 在上一篇文章中,主要讲的是请求和响应,项目里面views.py中的视图函数都是基于函数的,并且我们介绍了@api_view这个很有用的装 ...

  9. Django REST FrameWork中文教程3:基于类的视图

    我们也可以使用基于类的视图编写我们的API视图,而不是基于函数的视图.我们将看到这是一个强大的模式,允许我们重用常用功能,并帮助我们保持代码DRY. 使用基于类的视图重写我们的API 我们将首先将根视 ...

随机推荐

  1. Linux Mint---ATI显卡驱动安装篇

    显卡驱动可谓是至关重要,当时折腾debian驱动的时候可是弄了好几天才搞定的,现在却非常容易就是装上, 详见这篇博客:http://www.yyearth.com/article/14-03/amd1 ...

  2. Spring3.2+Struts2.3+Mybatis3.2整合使用(注解使用)

    0.包结构:

  3. QueryDict对象

    所在的包: django.http.QueryDict HttpRequest 对象中的 GET 和 POST 属性 都是 QueryDict类型 与python字典不同:QueryDict对象一个键 ...

  4. MVC中路由器程序

    MVC中路由器程序编写方式如下例子 把地址:/home/add?id=1 改写成:/home/add/1 把地址:/home/edit?id=1&sid=2 改写成:/home/edit/1_ ...

  5. [BZOJ2815][ZJOI2012]灾难 灭绝树+拓扑排序+lca

    灾难 [问题描述] 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那 么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的 生态灾难. 学过 ...

  6. Razor 常用方法

    结合wdate使用 //WdatePicker控件时间限制 @Html.TextBoxFor(model => model.BookingStart, new { @onClick = &quo ...

  7. POJ 3225.Help with Intervals-线段树(成段替换、区间异或、简单hash)

    POJ3225.Help with Intervals 这个题就是对区间的各种操作,感觉这道题写的一点意思都没有,写到后面都不想写了,而且更神奇的是,自己的编译器连结果都输不出来,但是交上就过了,也是 ...

  8. 分析dump

    一.使用jmap工具生成dump文件 二.MAT工具的下载和安装 三.使用MAT工具进行内存泄露分析  -- Step 1 :  ps –ef | grep <process> (whic ...

  9. HKSCS

    香港增补字符集(HKSCS) 背景介绍 背景资料 ======== 目前,大部份不同語文的電腦系統,都有不同的編碼標準.如中文的系統就有BIG5和GB2312/GBK.各種文字有不同的文字編碼,不同系 ...

  10. HashSet、LinkedHashSet和TreeSet

    关键技术: HashSet采用散列函数对元素进行排序,是专门为快速查询而设计的.存入HashSet的对象必须定义hashCode方法. TreeSet采用红黑树的数据结构进行排序元素,使用它可以从Se ...