引文

有朋友反映说对于 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_namecontext_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 类视图的更多相关文章

  1. django类视图的装饰器验证

    django类视图的装饰器验证 django类视图的get和post方法是由View内部调用dispatch方法来分发,最后调用as_view来完成一个视图的流程. 函数视图可以直接使用对应的装饰器 ...

  2. django类视图简单使用和源码解析

    django的类视图,CBV: 我们在开始接触django的时候,习惯于使用函数编写视图,即FBV.使用FBV时,我们只需要在路由匹配时,对应的路由下找到这个函数就可以了,这样做看似很和谐,但是有的时 ...

  3. 补充01 Django 类视图

    视图 函数视图[Function Base View] 以函数的方式定义的视图称为函数视图,函数视图便于理解.但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不 ...

  4. django类视图as_view()方法解析

    使用视图函数时,django完成URL解析之后,会直接把request对象以及URL解析器捕获的参数(比如re_path中正则表达捕获的位置参数或关键字参数)丢给视图函数,但是在类视图中,这些参数不能 ...

  5. django类视图的使用

    1 类视图引入 以函数的方式定义的视图称为函数视图,函数视图便于理解. 但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,代码可读性与复用性都不佳 ...

  6. django 类视图的使用

    使用django框架也有挺长时间了,但是一直都没有用过django的类视图,因为之前跟着网上教程学习时,觉得类视图是进阶的知识,可能目前还达不到吧 但今天在做项目的时候用到了,感觉真的太方便了吧,而且 ...

  7. 在DJANGO的类视图中实现登陆要求和权限保护

    以前接触的是基于函数的保护,网上材料比较多. 但基于类视图的很少. 补上! Decorating class-based views 装饰类视图 对于类视图的扩展并不局限于使用mixin.你也可以使用 ...

  8. Django内置的通用类视图

    1.ListView 表示对象列表的一个页面. 执行这个视图的时候,self.object_list将包含视图正在操作的对象列表(通常是一个查询集,但不是必须). 属性: model: 指定模型 te ...

  9. Part 4:表单和类视图--Django从入门到精通系列教程

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...

随机推荐

  1. Spring框架(2)---IOC装配Bean(xml配置方式)

    IOC装配Bean (1)Spring框架Bean实例化的方式提供了三种方式实例化Bean 构造方法实例化(默认无参数,用的最多) 静态工厂实例化 实例工厂实例化 下面先写这三种方法的applicat ...

  2. skywalking部署

    官方文档:Setup java agent Backend and UI 下载地址:http://skywalking.apache.org/downloads/ 解压后目录 部署UI和收集器 进入w ...

  3. 《C++ Primer Plus 第6版》学习笔记

    第三章.基本数据类型 整形 short:至少16位 int:至少与short一样长 long:至少32位,且至少与int一样长 long long:至少64位,且至少与long一样长 字符类型 cha ...

  4. CentOS5/6/7系统下搭建安装Amabari大数据集群时出现SSLError: Failed to connect. Please check openssl library versions.错误的解决办法(图文详解)

    不多说,直接上干货! ========================== Creating target directory... ========================== Comman ...

  5. 【原创】浅说windows下的中断请求级IRQL

    一 中断分类 根据中断源不同,可以将中断分为 硬件中断:硬件上产生的中断,可以来自处理器的内部和外部.处理器的外部中断可以来自各种PIN信号接口和Local APIC的LINT0和LINT1引脚,以及 ...

  6. Java并发编程-AbstractQueuedSynchronizer源码分析

    简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...

  7. python装饰器2:类装饰器

    装饰器1:函数装饰器 装饰器2:类装饰器 装饰器3:进阶 本文是装饰器相关内容的第二篇,关于类装饰器. "类装饰器"有两种解读方式:用来装饰类的装饰器:类作为装饰器装饰其它东西.你 ...

  8. 基础篇:8.如何定义变量?js变量有什么特点?

    书接上文,废话不多说,直接进入正题,下面我们一起来讨论js中的变量那些事! 那什么是变量? 变量是存储信息的容器,可以存储任何类型的数据. 如何定义变量呢? 变量可以使用短名称,如x,y:也可以是长名 ...

  9. keras入门(三)搭建CNN模型破解网站验证码

    项目介绍   在文章CNN大战验证码中,我们利用TensorFlow搭建了简单的CNN模型来破解某个网站的验证码.验证码如下: 在本文中,我们将会用Keras来搭建一个稍微复杂的CNN模型来破解以上的 ...

  10. SVN的工作原理及流程手册

    1.什么是SVN ? SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS.CVS,它采用了分支管理系统,它的设计目标就是取代CVS. 互联网上很多版本控制服务已从CVS迁 ...