CBV

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

Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:

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

使用class-based views(CBV)

如果用class-based view写的话,就是下面这样

from django.http import HttpResponse
from django.views import View class MyView(View):
    
def get(self, request,*args,**kwargs):
return HttpResponse('OK')

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

http协议支持的请求方式:
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

  get请求:    查看数据
  post请求:   添加数据
  delete请求:  删除数据
  put请求:   更新指定数据
  patch请求:  更新全部数据

  等

在url中,就这么写:

# urls.py
from django.conf.urls import url
from myapp.views import MyView urlpatterns = [
url(r'^index/$', MyView.as_view()), #执行dispatch方法
]

类的属性可以通过两种方法设置,第一种是常见的Python的方法,可以被子类覆盖。

from django.http import HttpResponse
from django.views import View class GreetingView(View):
name = "yuan"
def get(self, request):
return HttpResponse(self.name) # You can override that in a subclass class MorningGreetingView(GreetingView):
name= "alex"

第二种方法,你也可以在url中指定类的属性:

在url中设置类的属性Python

urlpatterns = [
url(r'^index/$', GreetingView.as_view(name="egon")),
]
避免csrf的方法:
全局:注释csrf中间件 from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
局部避免csrf的方式:
针对视图函数:# 避免csrf验证
@csrf_exempt
def foo(request):
return HttpResponse("foo") 针对CBV:
# 方式1
# @method_decorator(csrf_exempt,name="dispatch")
class IndexView(View):
# 方式2
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
print("hello world")
# 执行父类的dispatch方法
res=super(IndexView,self).dispatch(request, *args, **kwargs)
print("hello boy")
return res

回顾多重继承和Mixin

使用Mixin

我觉得要理解django的class-based-view(以下简称cbv),首先要明白django引入cbv的目的是什么。在django1.3之前,generic view也就是所谓的通用视图,使用的是function-based-view(fbv),亦即基于函数的视图。有人认为fbv比cbv更pythonic,窃以为不然。python的一大重要的特性就是面向对象。而cbv更能体现python的面向对象。cbv是通过class的方式来实现视图方法的。class相对于function,更能利用多态的特定,因此更容易从宏观层面上将项目内的比较通用的功能抽象出来。关于多态,不多解释,有兴趣的同学自己Google。总之可以理解为一个东西具有多种形态(的特性)。cbv的实现原理通过看django的源码就很容易明白,大体就是由url路由到这个cbv之后,通过cbv内部的dispatch方法进行分发,将get请求分发给cbv.get方法处理,将post请求分发给cbv.post方法处理,其他方法类似。怎么利用多态呢?cbv里引入了mixin的概念。Mixin就是写好了的一些基础类,然后通过不同的Mixin组合成为最终想要的类。

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

多重继承

回忆一下Animal类层次的设计,假设我们要实现以下4种动物:

  • Dog - 狗狗;
  • Bat - 蝙蝠;
  • Parrot - 鹦鹉;
  • Ostrich - 鸵鸟。

如果按照哺乳动物和鸟类归类,我们可以设计出这样的类的层次:

但是如果按照“能跑”和“能飞”来归类,我们就应该设计出这样的类的层次:

如果要把上面的两种分类都包含进来,我们就得设计更多的层次:

  • 哺乳类:能跑的哺乳类,能飞的哺乳类;
  • 鸟类:能跑的鸟类,能飞的鸟类。

这么一来,类的层次就复杂了:

如果要再增加“宠物类”和“非宠物类”,这么搞下去,类的数量会呈指数增长,很明显这样设计是不行的。

正确的做法是采用多重继承。首先,主要的类层次仍按照哺乳类和鸟类设计:

class Animal(object):
pass # 大类:
class Mammal(Animal):
pass class Bird(Animal):
pass # 各种动物:
class Dog(Mammal):
pass class Bat(Mammal):
pass class Parrot(Bird):
pass class Ostrich(Bird):
pass

现在,我们要给动物再加上RunnableFlyable的功能,只需要先定义好RunnableFlyable的类:

class Runnable(object):
def run(self):
print('Running...') class Flyable(object):
def fly(self):
print('Flying...'

对于需要Runnable功能的动物,就多继承一个Runnable,例如Dog

class Dog(Mammal, Runnable):
pass

对于需要Flyable功能的动物,就多继承一个Flyable,例如Bat

class Bat(Mammal, Flyable):
pass

通过多重继承,一个子类就可以同时获得多个父类的所有功能。

Mixin

在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为Mixin。

为了更好地看出继承关系,我们把RunnableFlyable改为RunnableMixinFlyableMixin。类似的,你还可以定义出肉食动物CarnivorousMixin和植食动物HerbivoresMixin,让某个动物同时拥有好几个Mixin:

class Dog(Mammal, RunnableMixin, CarnivorousMixin):
pass

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

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

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

class MyTCPServer(TCPServer, ForkingMixin):
pass

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

class MyUDPServer(UDPServer, ThreadingMixin):
pass

如果你打算搞一个更先进的协程模型,可以编写一个CoroutineMixin

class MyTCPServer(TCPServer, CoroutineMixin):
pass

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

rest_frameword学前准备的更多相关文章

  1. ASP.NET MVC学前篇之扩展方法、链式编程

    ASP.NET MVC学前篇之扩展方法.链式编程 前言 目的没有别的,就是介绍几点在ASP.NETMVC 用到C#语言特性,还有一些其他琐碎的知识点,强行的划分一个范围的话,只能说都跟MVC有关,有的 ...

  2. ASP.NET MVC学前篇之Lambda表达式、依赖倒置

    ASP.NET MVC学前篇之Lambda表达式.依赖倒置 前言 随着上篇文章的阅读,可能有的朋友会有疑问,比如(A.Method(xxx=>xx>yy);)类似于这样的函数调用语句,里面 ...

  3. ASP.NET MVC学前篇之Ninject的初步了解

    ASP.NET MVC学前篇之Ninject的初步了解 1.介绍 废话几句,Ninject是一种轻量级的.基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,因为这种IoC开 ...

  4. ASP.NET MVC学前篇之请求流程

    ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...

  5. 第43节:Java学前要点

    Java学前要点 01 学习Java,有人推荐去培训,有人说没用,其实有钱的,不知道如何学,或者逼不得已去的就可以,也有人自己为了不花这些钱,而选择自学,我觉得也行. 现在大部分人学东西要学的好,都是 ...

  6. 《Java程序设计》win10系统学前准备

    <Java程序设计>win10系统学前准备 Git的安装 在https://gitforwindows.org/中下载git for windows,下载完成后进行安装.当安装进行到这一步 ...

  7. 002 C#学前入门

    2016-01-16 1..Net平台  .Net FrameWork框架.Net FrameWork框架提供了一个稳定的运行环境,:来保障我们.Net平台正常的运转 2.C#语言 c sharp编程 ...

  8. 【IOS】1.学前准备

    OC 支持 GC 只在Mac OS X好用. IOS 不支持GC. iPhone开发环境必须是 Mac OS X Xcode包括 Xcode.app iPhone SDK iPhone Simulat ...

  9. IOS自学笔记1——学前准备

    函数的声明和定义: 在标准的C编译器中,定义的函数只能调用前面已经定义的函数.若在main()函数里要调用其他方法,这时得首先在main()上面声明要调用的函数,即函数的声明. C语言中,函数的声明和 ...

随机推荐

  1. 在easyUI开发中,出现jquery.easyui.min.js函数库问题

    easyUI是jquery的一个插件,是民间的插件.easyUI使用起来很方便,里面有网页制作的最重要的三大方块:javascript代码.html代码和Css样式.我们在导入easyUI库后,可以直 ...

  2. Python中enumerate函数用法详解

    enumerate函数用于遍历序列中的元素以及它们的下标,多用于在for循环中得到计数,enumerate参数为可遍历的变量,如 字符串,列表等 一般情况下对一个列表或数组既要遍历索引又要遍历元素时, ...

  3. iOS银联,支付宝,微信,ping++开发文档

    银联支付 银联支付目测只需两个参数 1.tn 其实就是订单号 2.mode 是测试环境还是线上环境 开发步骤 1.首先客户端浏览商品,点击下单,请求到达商户后台 2.商户后台在提交订单信息到银联后台 ...

  4. Eclipse下JRebel6.5.0热部署插件安装、破解及配置

    发现一个问题:如果安装了jRebel,但是并未对项目添加jRebel监听时,如果重写jar包中的类, 虽然重写后的类会得到编译(classes中的class已经是修改后的class),但是并不会调用重 ...

  5. 在C/C++程序中打印当前函数调用栈

    前几天帮同事跟踪的一个程序莫名退出,没有core dump(当然ulimit是打开的)的问题.我们知道,正常情况下,如果程序因为某种异常条件退出的话,应该会产生core dump,而如果程序正常退出的 ...

  6. Hibernate常用方法之_查询

    1.使用session的get方法 public User getUser(int id){ Session session = null; User user = null; try { sessi ...

  7. [Leetcode] search a 2d matrix 搜索二维矩阵

    Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...

  8. JS格式化时间(支持小程序,兼容IOS)

    })-(\d{})-(\d{})T(\d{}):(\d{}):(\d{})/ /** * @function format time * @param val, format * @return {s ...

  9. JAVA List 一边遍历一边删除元素

    JAVA List 一边遍历一边删除元素,报java.util.ConcurrentModificationException异常 2015年02月10日 14:42:49 zhanzkw 阅读数:3 ...

  10. 从零开始学习MXnet(四)计算图和粗细粒度以及自动求导

    这篇其实跟使用MXnet的关系不大,但对于我们理解深度学习的框架设计还是很有帮助的. 首先还是对promgramming models的一个简单介绍,这个东西实际上是在编译里面经常出现的东西,我们在编 ...