Diango博客--13.将“视图函数”类转化为“类视图”

文章目录

    • 0.思路引导
    • 1.ListView
    • 2.将 index 视图函数改写为类视图
    • 3.将 category 视图函数改写为类视图
    • 4.将 archive 视图函数改写成类视图
    • 5.将 tag 视图函数改写成类视图
    • 6.DetailView
    • 7.将DetailView视图函数改写成类视图

0.思路引导

1)在开发网站的过程中,有一些视图函数虽然处理的对象不同,但是其大致的代码逻辑是一样的。比如一个博客和一个论坛,通常其首页都是展示一系列的文章列表或者帖子列表;

2)对处理首页的视图函数来说,其处理的逻辑即:首先从数据库取出文章或者帖子列表,然后将这些数据传递给模板并渲染模板;

3)于是,django 把这些相同的逻辑代码抽取了出来,写成了一系列的通用视图函数,即基于类的通用视图(Generic Class Based View);

4)使用类视图是 django 推荐的做法,熟悉了类视图的使用方法后,能够减少视图函数的重复代码,节省开发时间。

接下来就让我们把博客应用中的视图函数改成基于类的通用视图。

1.ListView

在我们的博客应用中,有几个视图函数是从数据库中获取文章(Post)列表数据的:

文件位置:blog/views.py

def index(request):# ...def archive(request, year, month):# ...def category(request, pk):# ...def tag(request, pk):# ...

这些视图函数都是从数据库中获取文章(Post)列表,唯一的区别就是获取的文章列表可能不同。比如 index 获取全部文章列表,category 获取某个分类下的文章列表。

针对这种从数据库中获取某个模型列表数据(比如这里的 Post 列表)的视图,Django 专门提供了一个 ListView 类视图。

2.将 index 视图函数改写为类视图

文件位置:blog/views.py

原视图函数如下:


def index(request):post_list = Post.objects.all()return render(request, 'blog/index.html', context={'post_list': post_list})

修改成如下所示:

from django.views.generic import ListViewclass IndexView(ListView):model = Posttemplate_name = 'blog/index.html'context_object_name = 'post_list'

注意:

1)要写一个类视图,首先需要继承 django 提供的某个类视图。至于继承哪个类视图,需要根据你的视图功能而定。比如这里 IndexView 的功能是从数据库中获取文章(Post)列表,ListView 就是从数据库中获取某个模型列表数据的,所以 IndexView 继承 ListView。

2)model:将 model 指定为 Post,告诉 django 我要获取的模型是 Post。

3)template_name:指定这个视图即将去渲染的模板。

4)context_object_name:指定获取的模型列表数据保存的变量名,这个变量会被传递给模板。

接下来,需要更改blog 的 URL 配置。

文件位置:blog/urls.py

原文件如下:

app_name = 'blog'
urlpatterns = [path('', views.index, name='index'),...
]

修改为如下所示:

app_name = 'blog'
urlpatterns = [path('', views.IndexView.as_view(), name='index'),...
]

注意:
1)URL中每一个path对应着一个视图函数,这样当用户访问这个 URL 时,Django 就知道调用哪个视图函数去处理这个请求了。

2)在 Django 中 URL 模式的配置方式就是通过 url 函数将 URL 和视图函数绑定。比如 path(’’, views.index, name=‘index’),它的第一个参数是 URL 模式,第二个参数是视图函数 index。

3)对 url 函数来说,第二个参数传入的值必须是一个函数。而 IndexView 是一个类,不能直接替代 index 函数。好在将类视图转换成函数视图非常简单,只需调用类视图的 as_view() 方法即可。

3.将 category 视图函数改写为类视图

文件位置:blog/views.py

原视图函数如下:

def category(request, pk):"""定义 分类 视图"""# 记得在开始部分导入 Category 类cate = get_object_or_404(Category, pk=pk)post_list = Post.objects.filter(category=cate)#.order_by('-created_time')return render(request, 'blog/index.html', context={'post_list': post_list})

初步改写如下:

class CategoryView(ListView):model = Posttemplate_name = 'blog/index.html'context_object_name = 'post_list'def get_queryset(self):cate = get_object_or_404(Category, pk=self.kwargs.get('pk'))return super(CategoryView, self).get_queryset().filter(category=cate)

注意:

1)和 IndexView 不同的地方是,我们覆写了父类的 get_queryset 方法。该方法默认获取指定模型的全部列表数据,为了获取指定分类下的文章列表数据,我们覆写该方法,通过filter改变它的默认行为。

2)在类视图中,从 URL 捕获的路径参数值保存在实例的 kwargs 属性(是一个字典)里,非路径参数值保存在实例的 args 属性(是一个列表)里。

3)所以我们使了 self.kwargs.get(‘pk’) 来获取从 URL 捕获的分类 id 值。然后调用父类的 get_queryset 方法获得全部文章列表,紧接着就对返回的结果调用了 filter 方法来筛选该分类下的全部文章并返回。

4)此外我们可以看到 CategoryView 类中指定的属性值和 IndexView 中是一模一样的,所以如果为了进一步节省代码,甚至可以直接继承 IndexView。

优化后如下:

class CategoryView(IndexView):def get_queryset(self):cate = get_object_or_404(Category, pk=self.kwargs.get('pk'))return super(CategoryView, self).get_queryset().filter(category=cate)

接下俩,在 URL 配置中把 category 视图替换成类视图 CategoryView:

文件位置:blog/urls.py

app_name = 'blog'
urlpatterns = [...path('categories/<int:pk>/', views.CategoryView.as_view(), name='category'),
]

4.将 archive 视图函数改写成类视图

文件位置:blog/views.py

原视图函数如下:

def archive(request, year, month):"""定义 归档 视图"""post_list = Post.objects.filter(created_time__year=year,created_time__month=month)#.order_by('-created_time')return render(request, 'blog/index.html', context={'post_list': post_list})

改写如下:

 class ArchiveView(IndexView):def get_queryset(self):year = self.kwargs.get('year')month = self.kwargs.get('month')return super().get_queryset().filter(created_time__year=year, created_time__month=month)

接下俩,在 URL 配置中把 archive 视图替换成类视图 ArchiveView:

文件位置:blog/urls.py

app_name = 'blog'
urlpatterns = [...path('archives/<int:year>/<int:month>/', views.ArchiveView.as_view(), name='archive'),
]

5.将 tag 视图函数改写成类视图

文件位置:blog/views.py

原视图函数如下:

def tag(request, pk):# 记得在开始部分导入 Tag 类t = get_object_or_404(Tag, pk=pk)post_list = Post.objects.filter(tags=t)#.order_by('-created_time')return render(request, 'blog/index.html', context={'post_list': post_list})

改写如下:

 class TagView(IndexView):def get_queryset(self):t = get_object_or_404(Tag, pk=self.kwargs.get('pk'))return super().get_queryset().filter(tags=t)

接下俩,在 URL 配置中把 tag 视图替换成类视图 TagView:

文件位置:blog/urls.py

app_name = 'blog'
urlpatterns = [...path('tags/<int:pk>/', views.TagView.as_view(), name='tag'),
]

6.DetailView

除了从数据库中获取模型列表的数据外,从数据库获取模型的一条记录数据也是常见的需求。

比如查看某篇文章的详情,就是从数据库中获取这篇文章的记录然后渲染模板。

对于这种类型的需求,django 提供了一个 DetailView 类视图。

7.将DetailView视图函数改写成类视图

接下俩,将 detail 视图函数转换为等价的类视图 PostDetailView视图

文件位置:blog/views.py

原视图函数如下:

def detail(request, pk):"""定义文章详情页视图"""post = get_object_or_404(Post, pk=pk)#阅读量+1post.increase_views()md = markdown.Markdown(extensions=['markdown.extensions.extra','markdown.extensions.codehilite',# 'markdown.extensions.toc',# 记得在顶部引入 TocExtension 和 slugifyTocExtension(slugify=slugify),])post.body = md.convert(post.body)m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)post.toc = m.group(1) if m is not None else ''return render(request, 'blog/detail.html', context={'post': post})

改写如下:

class PostDetailView(DetailView):model = Posttemplate_name = 'blog/detail.html'context_object_name = 'post'def get(self, request, *args, **kwargs):# 覆写 get 方法的目的是因为每当文章被访问一次,就得将文章阅读量 +1# get 方法返回的是一个 HttpResponse 实例# 之所以需要先调用父类的 get 方法,是因为只有当 get 方法被调用后,# 才有 self.object 属性,其值为 Post 模型实例,即被访问的文章 postresponse = super().get(request, *args, **kwargs)# 将文章阅读量 +1# 注意 self.object 的值就是被访问的文章 postself.object.increase_views()# 视图必须返回一个 HttpResponse 对象return responsedef get_object(self, queryset=None):# 覆写 get_object 方法的目的是因为需要对 post 的 body 值进行渲染post = super().get_object(queryset=None)md = markdown.Markdown(extensions=['markdown.extensions.extra','markdown.extensions.codehilite',# 记得在顶部引入 TocExtension 和 slugifyTocExtension(slugify=slugify),])post.body = md.convert(post.body)m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)post.toc = m.group(1) if m is not None else ''return post

注意:

1)首先我们为 PostDetailView 类指定了一些属性的值,这些属性的含义和 ListView 中一样。

2)紧接着我们覆写了 get 方法。这对应着 detail 视图函数中将 post 的阅读量 +1 的那部分代码。事实上,你可以简单地把 get 方法的调用看成是 detail 视图函数的调用。

3)接着我们又复写了 get_object 方法。对应着 detail 视图函数中根据文章的 id(也就是 pk)获取文章,然后对文章的 post.body 进行 Markdown 解析。

4)get 方法看成是 detail 视图函数,至于其它的像 get_object、get_context_data 都是辅助方法,这些方法最终在 get 方法中被调用,这里你没有看到被调用的原因是它们隐含在了 super(PostDetailView, self).get(request, *args, **kwargs) 即父类 get 方法的调用中。最终传递给浏览器的 HTTP 响应就是 get 方法返回的 HttpResponse 对象。

接下俩,在 URL 配置中把 detail 视图替换成类视图 PostDetailView:

文件位置:blog/urls.py

app_name = 'blog'
urlpatterns = [...path('posts/<int:pk>', views.PostDetailView.as_view(), name = 'detail'),
]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/452411.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

es6之数据结构 set,WeakSet,mapWeakMap

{let list new Set();list.add(1);list.add(2);list.add(1);console.log(list); //Set(2) {1, 2} let arr[1,2,3,1,2] let list2new Set(arr); console.log(list2); //Set(3) {1, 2, 3} } Set ES6 提供了新的数据结构 Set。它类似于数组&#xff0c;但是成员的值都是唯一的&a…

关于C语言中继承和多态的实现

以下的内容综合了多篇文章&#xff0c;加上一点自己的理解而成。目的为了给自己阅读他们文章后做一个笔记。在末尾给出了这些文章的地址。 多态的实现可以采用以下几种方式&#xff1a; (1)使用 vod * (万能指针)来实现“编译时多态”。 (2)使用函数指针来实现“运行时…

边界测试

边界条件边界测试是单元测试中最后的也可能是最重要的任务。 软件常常在它的边界上失效&#xff0c;例如&#xff0c;处理n元数组的第n个元素时&#xff0c;或做到i次循环中的第i次重复时&#xff0c;往往会发生错误。 使用刚好小于、刚好等于和刚好大于最大值或最小值的数据结…

阿里云上Kubernetes集群联邦

摘要&#xff1a; kubernetes集群让您能够方便的部署管理运维容器化的应用。但是实际情况中经常遇到的一些问题&#xff0c;就是单个集群通常无法跨单个云厂商的多个Region&#xff0c;更不用说支持跨跨域不同的云厂商。这样会给企业带来一些担忧&#xff0c;如何应对可用区级别…

缺氧游戏计算机,缺氧PC最低什么配置一览 你觉得高吗

缺氧PC最低什么配置一览&#xff0c;你觉得高吗。游戏对于电脑有不同程度的要求&#xff0c;缺氧这款游戏也有着自己的配置要求&#xff0c;看看下面的缺氧PC最低什么配置一览&#xff0c;你的硬件够得上吗。缺氧最低配置&#xff1a;首先公布的是官 方配置需求&#xff0c;目前…

Diango博客--14.使用 Django 项目中的 ORM 编写伪造测试数据脚本

文章目录0.思路引导1.脚本目录结构2.使用 Faker 快速生成测试数据3.批量生成测试数据4.执行脚本5.效果展示0.思路引导 1&#xff09;为了防止博客首页展示的文章过多以及提升加载速度&#xff0c;可以对文章列表进行分页展示。 2&#xff09;不过这需要比较多的文章才能达到分…

基于Sql Server 2008的分布式数据库的实践

配置Sql Server 2008&#xff08;Win7&#xff09; 1.打开SQL server2012&#xff0c;使用windows身份登录 2.登录后&#xff0c;右键选择“属性”。左侧选择“安全性”&#xff0c;选中右侧的“SQL Server 和 Windows 身份验证模式”以启用混合登录模式 3.选择“连接”&#x…

横向技术分析C#、C++和Java优劣

本文将从技术人员的角度横向分析C#、C和Java优劣&#xff0c;其实选择Java阵营还是.NET阵营&#xff0c;大家可以根据自己的实际需要来确定。 C#诞生之日起&#xff0c;关于C#与Java之间的论战便此起彼伏&#xff0c;至今不辍。抛却Microsoft与Sun之间的恩怨与口角&#xff0c;…

软件测试中的存根程序

存根程序用来代替被测试的模块所调用的模块&#xff0c;因此存根程序也称为“虚拟子程序”&#xff0c;它利用被它代替的模块的接口&#xff0c;只做尽可能少的数据操作。

计算机网络应用云计算,计算机网络云计算的类型

原标题&#xff1a;计算机网络云计算的类型随着现代计算机网络技术的不断发展&#xff0c;越来越多的与计算机网络有关的现代化技术得以出现&#xff0c;并且有着广泛的应用&#xff0c;其中云计算技术就是比较常见的一种&#xff0c;在实际应用中发挥着较高的价值。在信息时代…

sublime_text快捷键

1、注释&#xff1a;选中文本后&#xff0c;CTRL / 2、CTRL N,CTRLS&#xff0c;保存成.html文件后&#xff0c;只需要输入感叹号&#xff01;&#xff0c;然后tab键&#xff0c;即可打印出基本的html格式&#xff01;转载于:https://www.cnblogs.com/JAVA-STUDYER/p/855040…

Diango博客--15.通过 Django Pagination 实现简单分页(一)

文章目录0.思路引导1.Paginator 类的常用方法2.用 Paginator 给文章列表分页3.在模板中设置分页导航4.效果展示0.思路引导 1&#xff09;当博客上发布的文章越来越多时&#xff0c;通常需要进行分页显示&#xff0c;以免所有的文章都堆积在一个页面&#xff0c;影响用户体验。…

SpringMVC 测试 mockMVC

SpringMVC测试框架 基于RESTful风格的SpringMVC的测试&#xff0c;我们可以测试完整的Spring MVC流程&#xff0c;即从URL请求到控制器处理&#xff0c;再到视图渲染都可以测试。 一 MockMvcBuilder MockMvcBuilder是用来构造MockMvc的构造器&#xff0c;其主要有两个实现&…

自顶向下和自底向上测试的优缺点

自顶向下测试方法的主要优点是不需要测试驱动程序&#xff0c;能够在测试阶段的早期实现并验证系统的主要功能&#xff0c;而且能在早期发现上层模块的接口错误。 自顶向下测试方法的主要缺点是需要存根程序&#xff0c;可能遇到与此相联系的测试困难&#xff0c;低层关键模块中…

C++ class中的静态(static)成员

C class中的静态(static)成员 &#xff08;1&#xff09; 静态数据成员 ①一般地静态数据成员在该类定义之外被初始化&#xff0c;如同一个成员函数被定义在类定义之外一样。在这种定义中的静态成员的名字必须被其类名限定修饰&#xff0c;例如下面是_interestRate的初始…

用计算机弹可惜不是你,可惜不是你 还是幸亏不是你

一、 你没有再挽留 我也没有再回头 就这样 无风无雨也无晴 无疾而终二、 是我孤陋寡闻不知你心有人三、 如果作业有葬礼,全体学生定当盛装出席.四、 纵使我有千般好 你也看不到 因为你没有一双爱我的眼睛五、 原来暂时共你没缘分 来年先会变得更合衬六、 真的别回头 你有未来 你…

PHP 完整实战23种设计模式

PHP实战创建型模式 单例模式 工厂模式 抽象工厂模式 原型模式 建造者模式 PHP实战结构型模式 桥接模式 享元模式 外观模式 适配器模式 装饰器模式 组合模式 代理模式 过滤器模式 PHP实战行为型模式 模板模式 策略模式 状态模式 观察者模式 责任链模式 访问者模…

Diango博客--16.稳定易用的 Django 分页库,完善分页功能(二)

文章目录0.思路引导1.分页效果概述2.分页思路3.Django 第三方拓展&#xff1a;django-pure-pagination4.自定义模板0.思路引导 1&#xff09;在前面我们通过 Django Pagination 实现简单分页 中&#xff0c;我们实现了一个简单的分页导航。但效果有点差强人意&#xff0c;我们…

回归测试

在集成测试过程中&#xff0c;每当一个新模块结合进来时&#xff0c;程序就发生了变化&#xff1a;建立了新的数据流路径&#xff0c;可能出现了新的I/O操作&#xff0c;激活了新的控制逻辑。在集成测试的范畴中&#xff0c;回归测试是指重新执行已经做过的测试的某个子集&…

不同的写法 其中 1 2 (试了下 没有效果 ,先记载这里把)

转载于:https://www.cnblogs.com/kaibindirver/p/9145455.html