Django学习笔记之Class-Based-View


Posted in Python onFebruary 15, 2017

前言

大家都知道其实学习Django非常简单,几乎不用花什么精力就可以入门了。配置一个url,分给一个函数处理它,返回response,几乎都没有什么很难理解的地方。

写多了,有些问题才逐渐认识到。比如有一个view比较复杂,调用了很多其他的函数。想要把这些函数封装起来,怎么办?当然,可以用注释#------view------这样将函数隔离开,这种方法太low了,简直是在骗自己,连封装都算不上。

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

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

使用class-based views

如果我们要写一个处理GET方法的view,用函数写的话是下面这样。

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

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

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

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

在url中,就这么写:

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

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

from django.http import HttpResponse
from django.views import View
 
class GreetingView(View):
 greeting = "Good Day"
 
 def get(self, request):
  return HttpResponse(self.greeting)
 
# You can override that in a subclass
 
class MorningGreetingView(GreetingView):
 greeting = "Morning to ya"

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

在url中设置类的属性Python

urlpatterns = [
 url(r'^about/$', GreetingView.as_view(greeting="G'day")),
]

使用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写在左边。Mixin也是比较复杂的技术,本文不详细说了,以后写一篇针对Mixin的文章吧。

使用装饰器

在CBV中,可以使用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)

也可以写在类上面,传入方法的名字。

@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
 template_name = 'secret.html'

如果有多个装饰器装饰一个方法,可以写成一个list。例如,下面这两种写法是等价的。

decorators = [never_cache, login_required]
 
@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
 template_name = 'secret.html'
 
@method_decorator(never_cache, name='dispatch')
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
 template_name = 'secret.html'

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Python 相关文章推荐
python自动化测试之从命令行运行测试用例with verbosity
Sep 28 Python
Python实现快速多线程ping的方法
Jul 15 Python
Python调用SQLPlus来操作和解析Oracle数据库的方法
Apr 09 Python
python简易实现任意位数的水仙花实例
Nov 13 Python
利用python和ffmpeg 批量将其他图片转换为.yuv格式的方法
Jan 08 Python
python 切换root 执行命令的方法
Jan 19 Python
python实现转盘效果 python实现轮盘抽奖游戏
Jan 22 Python
Python 判断图像是否读取成功的方法
Jan 26 Python
python 实现简单的FTP程序
Dec 27 Python
简单了解python filter、map、reduce的区别
Jan 14 Python
TensorFlow通过文件名/文件夹名获取标签,并加入队列的实现
Feb 17 Python
详解Django ORM引发的数据库N+1性能问题
Oct 12 Python
关于Python面向对象编程的知识点总结
Feb 14 #Python
Django日志模块logging的配置详解
Feb 14 #Python
深入理解Python对Json的解析
Feb 14 #Python
Python 2与Python 3版本和编码的对比
Feb 14 #Python
利用Python爬虫给孩子起个好名字
Feb 14 #Python
python 出现SyntaxError: non-keyword arg after keyword arg错误解决办法
Feb 14 #Python
让python 3支持mysqldb的解决方法
Feb 14 #Python
You might like
在线竞拍系统的PHP实现框架(二)
2006/10/09 PHP
PHP实现的sqlite数据库连接类
2014/12/12 PHP
PHP 验证登陆类分享
2015/03/13 PHP
PHP Redis扩展无法加载的问题解决方法
2019/08/22 PHP
爱恋千雪-US-AscII加密解密工具(网页加密)下载
2007/06/06 Javascript
最佳JS代码编写的14条技巧
2011/01/09 Javascript
解析Jquery中如何把一段html代码动态写入到DIV中(实例说明)
2013/07/09 Javascript
批量修改标签css样式以input标签为例
2014/07/31 Javascript
基于JavaScript实现动态添加删除表格的行
2016/02/01 Javascript
jQuery使用Selectator插件实现多选下拉列表过滤框(附源码下载)
2016/04/08 Javascript
jQuery插件Echarts实现的双轴图效果示例【附demo源码下载】
2017/03/04 Javascript
利用js定义一个导航条菜单
2017/03/14 Javascript
深入理解jquery的$.extend()、$.fn和$.fn.extend()
2017/07/08 jQuery
jquery+css实现下拉列表功能
2017/09/03 jQuery
swiper.js插件实现pc端文本上下滑动功能示例
2018/12/03 Javascript
原生js实现的移动端可拖动进度条插件功能详解
2019/08/15 Javascript
简述ES6新增关键字let与var的区别
2019/08/23 Javascript
VUE单页面切换动画代码(全网最好的切换效果)
2019/10/31 Javascript
微信小程序关键字变色实现代码实例
2019/12/13 Javascript
[39:08]完美世界DOTA2联赛PWL S3 LBZS vs CPG 第一场 12.12
2020/12/16 DOTA
python 循环while和for in简单实例
2016/08/16 Python
浅谈flask截获所有访问及before/after_request修饰器
2018/01/18 Python
详解pyinstaller生成exe的闪退问题解决方案
2020/06/19 Python
通过Django Admin+HttpRunner1.5.6实现简易接口测试平台
2020/11/11 Python
新秀丽拉杆箱美国官方网站:Samsonite美国
2016/07/25 全球购物
俄罗斯在线服装店:STOLNIK
2021/03/07 全球购物
最新大学毕业求职简历的自我评价
2013/10/18 职场文书
小学家长会邀请函
2014/01/23 职场文书
户外亲子活动策划方案
2014/02/07 职场文书
新闻专业学生的自我评价
2014/02/13 职场文书
讲文明树新风公益广告宣传方案
2014/02/25 职场文书
莫言诺贝尔获奖演讲稿
2014/05/21 职场文书
双拥工作宣传标语
2014/06/26 职场文书
2014年商场国庆节活动策划方案
2014/09/16 职场文书
2015年度服装销售工作总结
2015/03/31 职场文书
node快速搭建后台的实现步骤
2022/02/18 NodeJs