Django 类视图
引文
有朋友反映说对于 Django 的 Class-Based-View(基于类的通用视图)还有很多不明白的地方,因此接下来我会在文章中讲解几个常用的具有代表性的基于类的视图用法,并在适当的源码层面下讲解其机理和如何按照我们的需要拓展它。
所有的类视图都继承django.views.generic.base.View类。
TemplateView
这可能是最简单的通用类视图。一般在仅仅渲染一个模板时派上用场。可直接在URLconf中使用as_view()方法,如下所示:
from django.urls import path
from django.views.generic import TemplateView urlpatterns = [
path('about/', TemplateView.as_view(template_name="about.html")),
]
ListView
从名字我们可以对其功能略窥一二,ListView 用于列出一系列 Model 对象集合(比如文章列表)。
在开发一个网站时,我们常常需要获取存储在数据库中的某个 Model 的列表,比如 Blog 要获取文章(Article)列表以显示到首页,通常我们都会写如下的视图函数来满足我们的需求:

当然这仅仅是一个最为基本的视图函数的例子,Django 开发者发现,如果项目里有大量的视图都是实现类似于上面这种获取存储在数据库中的某个 Model 的列表的功能的话,会不断地重复书写诸如下面的代码:

就是不断地获取 Model 列表然后渲染模板文件,Django 说写多了开发人员就觉得无聊了,那我们何不把这些逻辑抽象出来放到一个类里?于是 Django 帮我们写好了一个类,专门用于处理上面的情况,这就是 ListView,将上面的视图函数转写成类视图如下:

首先看看 get_queryset() 方法,它完成的功能和 article_list = Article.objects.all() 这句代码类似,获取某个 Model 的列表(这里是文章列表),其中 article_list 就是 context_object_name 属性值。
同时我们加入了自己的逻辑,即对 article_list 中的各个 article 进行了 markdwon 拓展。假如仅仅只需要获取 article_list ,则甚至可以不用复写 get_queryset 方法,只需指定一个 model 属性,告诉 Django 去获取哪个 model 的列表就可以了,像这样:

第二个复写的方法是 get_context_data() 方法,这个方法是用来给传递到模板文件的上下文对象(context)添加额外的内容的(context 的概念在前面的教程中已有介绍,如果这里不懂的话我再简单解释一下,我们在模板文件中会使用 {{ }} 这样的标签来包裹模板变量,这些变量哪里来的?就是视图函数通过 context 传递到模板的)。
我们这里因为首页需要显示分类信息,因此我们把 category_list 通过 get_context_data 方法加入了 context 对象,视图函数再帮我们把 context 传递给模板。return super(IndexView, self).get_context_data(**kwargs) 语句的作用是添加了 category_list 到上下文中,还要把默认的一些上下文变量也返回给视图函数,以便其后续处理。
现在有了 model 列表,context,按照视图函数的逻辑应该是把这些传递给模板了,ListView 通过指定 template_name 属性来指定需要渲染的模板,而 context_object_name 是给 get_queryset 方法返回的 model 列表重新命名的,因为默认返回的 model 列表其名字是 object_list,为了可读性,我们可以通过 context_object_name 来重新指定,例如我们这里指定为 article_list。
return render_to_response(‘blog/index.html’,context) 的功能在 ListView 中 Django 已经默认帮我们做了,翻看其源代码就会知道:

如果你改变渲染模板的一些行为,通过复写 render_to_response 方法即可。
以上方法在类视图调用 as_view() 方法后会被自动调用。
ListView总结
ListView 主要用在获取某个 model 列表中
通过 template_name 属性来指定需要渲染的模板,通过 context_object_name 属性来指定获取的 model 列表的名字,否则只能通过默认的 object_list 获取
复写 get_queryset 方法以增加获取 model 列表的其他逻辑
复写 get_context_data 方法来为上下文对象添加额外的变量以便在模板中访问
DetailView
前面的 ListView 用于获取某个 model 的列表,获取的是一系列对象,但获取单个mdoel对象也是很常见的,比如 Blog 里点击某篇文章后进入文章的详情页,这里获取的就是点击这篇文章。我们通常会写如下视图函数:

同样的,如果这种需求多的话,开发人员就需要枯燥而乏味地大量重复写 article = get_object_or_404(Article,pk=article_id) 这样的句子,Django 通过 DetailView 来把这种逻辑抽象出来,把上面的视图函数转成类视图:

model 属性告诉 Django 是获取哪个 model 对应的单个对象,template_name,context_object_name 属性和 ListView 中是一样的作用,pk_url_kwarg 相当于视图函数中的 article_id 参数(也是URLconf中的id参数),已告诉 Django 获取的是 id 为多少的 model 实例。
get_object() 方法默认情况下获取 id 为pk_url_kwarg 的对象,如果需要在获取过程中对获取的对象做一些处理,比如对文章做 markdown 拓展,通过复写 get_object 即可实现。
之后的处理就和 ListView 类似了,已经实现了 render_to_response 方法来渲染模板。
以上方法在类视图调用 as_view() 方法后会被自动调用。
DetailView 总结
DetailView主要用在获取某个 model 的单个对象中
通过 template_name 属性来指定需要渲染的模板,通过 context_object_name 属性来指定获取的 model 对象的名字,否则只能通过默认的 object 获取
复写 get_object 方法以增加获取单个 model 对象的其他逻辑
复写 get_context_data 方法来为上下文对象添加额外的变量以便在模板中访问
使用类的通用视图的好处
通过上面的例子你可能并未体会到使用类的通用视图的好处,毕竟我们写的基于函数的视图似乎代码量更短,但这仅仅是因为例子简单而已。
同时别忘了,类是可以被继承的,假如我们已经写好了一个基于类的通用视图,要对其拓展功能,只需继承原本这个类视图即可,而如果写的是函数呢?拓展性就没有这么灵活,可能需要使用到装饰器等高级技巧,或甚至不得不重复一段代码到新拓展的视图函数中。
但本质上而言,基于类的通用视图依然是一个视图函数,因为最终调用时我们会通过 genericview.as_view() 方法把类视图转换成一般的视图,url 配置是这样的:

因此,基于类的视图并非什么新的东西,只是为了方便而对一般的视图另一种形式的改写而已,理解了一般的视图写法后,通过阅读其官方文档和类视图的源码,很快就能掌握如何写好类视图了。
至此。转载请注明出处。
[参考:Django官方文档 https://docs.djangoproject.com/zh-hans/2.0]

Django 类视图的更多相关文章
- django类视图的装饰器验证
django类视图的装饰器验证 django类视图的get和post方法是由View内部调用dispatch方法来分发,最后调用as_view来完成一个视图的流程. 函数视图可以直接使用对应的装饰器 ...
- django类视图简单使用和源码解析
django的类视图,CBV: 我们在开始接触django的时候,习惯于使用函数编写视图,即FBV.使用FBV时,我们只需要在路由匹配时,对应的路由下找到这个函数就可以了,这样做看似很和谐,但是有的时 ...
- 补充01 Django 类视图
视图 函数视图[Function Base View] 以函数的方式定义的视图称为函数视图,函数视图便于理解.但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不 ...
- django类视图as_view()方法解析
使用视图函数时,django完成URL解析之后,会直接把request对象以及URL解析器捕获的参数(比如re_path中正则表达捕获的位置参数或关键字参数)丢给视图函数,但是在类视图中,这些参数不能 ...
- django类视图的使用
1 类视图引入 以函数的方式定义的视图称为函数视图,函数视图便于理解. 但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,代码可读性与复用性都不佳 ...
- django 类视图的使用
使用django框架也有挺长时间了,但是一直都没有用过django的类视图,因为之前跟着网上教程学习时,觉得类视图是进阶的知识,可能目前还达不到吧 但今天在做项目的时候用到了,感觉真的太方便了吧,而且 ...
- 在DJANGO的类视图中实现登陆要求和权限保护
以前接触的是基于函数的保护,网上材料比较多. 但基于类视图的很少. 补上! Decorating class-based views 装饰类视图 对于类视图的扩展并不局限于使用mixin.你也可以使用 ...
- Django内置的通用类视图
1.ListView 表示对象列表的一个页面. 执行这个视图的时候,self.object_list将包含视图正在操作的对象列表(通常是一个查询集,但不是必须). 属性: model: 指定模型 te ...
- Part 4:表单和类视图--Django从入门到精通系列教程
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...
随机推荐
- python中np.multiply()、np.dot()和星号(*)三种乘法运算的区别(转)
为了区分三种乘法运算的规则,具体分析如下: import numpy as np 1. np.multiply()函数 函数作用 数组和矩阵对应位置相乘,输出与相乘数组/矩阵的大小一致 1.1数组场景 ...
- spring cloud+.net core搭建微服务架构:服务注册(一)
背景 公司去年开始使用dotnet core开发项目.公司的总体架构采用的是微服务,那时候由于对微服务的理解并不是太深,加上各种组件的不成熟,只是把项目的各个功能通过业务层面拆分,然后通过nginx代 ...
- [Shell]Shell调用并获取执行jar包后的返回值
----------------------------------------------------------------- 原创博文,如需转载请注明出处! 博主:疲惫的豆豆 链接:http:/ ...
- java jar 后台运行
nohup java -jar $APP_NAME.jar >/dev/null &
- WebAssembly是解决JavaScript 痼疾的银弹?
写在前面 <没有银弹>是 Fred Brooks 在 1987 年所发表的一篇关于软件工程的经典论文.该论文的主要论点是,没有任何一项技术或方法可以能让软件工程的生产力在十年内提高十倍. ...
- 【bioinfo】生物信息学——代码遇见生物学的地方
注:从进入生信领域到现在,已经过去快8年了.生物信息学包含了我最喜欢的三门学科:生物学.计算机科学和数学.但是如果突然问起,什么是生物信息学,我还是无法给出一个让自己满意的答案.于是便有了这篇博客. ...
- Java爬取网络博客文章
前言 近期本人在某云上购买了个人域名,本想着以后购买与服务器搭建自己的个人网站,由于需要筹备的太多,暂时先搁置了,想着先借用GitHub Pages搭建一个静态的站,搭建的过程其实也曲折,主要是域名地 ...
- SHELL脚本--变量(基础)
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 变量存在于内存中.假设变量str,设置或修改变量属性时,不带$ ...
- C# XML入门
什么是XML? XML:可扩展标记语言. XML的作用: 纯文本,兼容性强. 和HTML的区别: xml: 主要用来处理.存储数据.无规定标签,可扩展. html:对数据的显示和描述. 语法标签固定. ...
- VS2013 OpenGL 开发程序时: error LNK2019: 无法解析的外部符号 __imp____glutInitWithExit@12,error LNK2019: 无法解析的外部符号 __imp____glutCreateWindowWithExit@8
环境:Windows 下 OpenGL ,Used in VS2013 前言:刚接触 OpenGL 的人,第一件事当然就是配置环境,说起配置环境 OpenGL 和 DirectX 相差不多,同时也基本 ...