引文

有朋友反映说对于 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. 从零開始学Xamarin.Forms(一) 概述

        Xamarin 读 "ˈzæmərin",是一个基于开源项目mono的可以使用C#开发的收费的跨平台(iOS.Android.Windows Phone.Mac)解决方式. ...

  2. mysql 开发进阶篇系列 20 MySQL Server(innodb_lock_wait_timeout,innodb_support_xa,innodb _log_*)

    1. innodb_lock_wait_timeout mysql 可以自动监测行锁导致的死锁并进行相应的处理,但是对于表锁导致的死锁不能自动监测,所以该参数主要用于,出现类似情况的时候等待指定的时间 ...

  3. Android--通知之Toast

    前言 这篇博客讲解一下Android下的一个简单信息提示的方式:Toast.如果一直看我的博客,会发现在之前的Demo中,一直有用到Toast去提示消息,在这篇博客中就专门讲它.Toast提供一个浮动 ...

  4. python三大神器之pip

    pip是一款管理python各类包和库的工具,非常好用.下文介绍常用的一些命令. ● 安装:pip install 库名 也可以指定版本:pip install 库名=版本 ● 卸载:pip unin ...

  5. MySQL中支持emoji表情的存储

    由于需要实现emoji表情评论的功能,所以数据库需要支持emoji表情的存储,根据查询的资料最终实现了该功能,现将实现的过程以及过程遇到的一些问题记录下来,供大家参考和交流. mysql的utf8编码 ...

  6. 面向连接的TCP概述

    TCP连接概述     TCP是因特网运输层面向连接的(connection-oriented)可靠运输协议.之所以说它是面向连接的是因为  一个应用进程向另外一个应用进程发送数据之前,两个进程必须先 ...

  7. [转]Ble蓝牙的使用手册

    本文转自:https://blog.csdn.net/dodan/article/details/52060446 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...

  8. [转]使用jenkins实现持续集成

    本文转自:https://www.cnblogs.com/zishengY/p/7170656.html 一.jenkins 介绍 它是一个自动化的周期性的集成测试过程,从检出代码.编译构建.运行测试 ...

  9. Web下的HTTPS应用

    ---------------------------------------------------------------------------------------------------- ...

  10. 第四讲 smart qq 获取联系人信息 ,分组 好友 群聊

    首先从post一下  http://s.web2.qq.com/api/get_user_friends2 这个链接获取分组categories ,好友信息 friends,info. string ...