建设通属于官方网站,成都设计公司创业园,网上哪个网站做的系统好用吗,建设工程材料信息价查什么网站文章目录0.思路引导1.ListView2.将 index 视图函数改写为类视图3.将 category 视图函数改写为类视图4.将 archive 视图函数改写成类视图5.将 tag 视图函数改写成类视图6.DetailView7.将DetailView视图函数改写成类视图0.思路引导
1#xff09;在开发网站的过程中#xff0c;…
文章目录0.思路引导1.ListView2.将 index 视图函数改写为类视图3.将 category 视图函数改写为类视图4.将 archive 视图函数改写成类视图5.将 tag 视图函数改写成类视图6.DetailView7.将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.htmlcontext_object_name post_list注意
1要写一个类视图首先需要继承 django 提供的某个类视图。至于继承哪个类视图需要根据你的视图功能而定。比如这里 IndexView 的功能是从数据库中获取文章Post列表ListView 就是从数据库中获取某个模型列表数据的所以 IndexView 继承 ListView。
2model将 model 指定为 Post告诉 django 我要获取的模型是 Post。
3template_name指定这个视图即将去渲染的模板。
4context_object_name指定获取的模型列表数据保存的变量名这个变量会被传递给模板。
接下来需要更改blog 的 URL 配置。
文件位置blog/urls.py
原文件如下
app_name blog
urlpatterns [path(, views.index, nameindex),...
]修改为如下所示
app_name blog
urlpatterns [path(, views.IndexView.as_view(), nameindex),...
]注意 1URL中每一个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, pkpk)post_list Post.objects.filter(categorycate)#.order_by(-created_time)return render(request, blog/index.html, context{post_list: post_list})初步改写如下
class CategoryView(ListView):model Posttemplate_name blog/index.htmlcontext_object_name post_listdef get_queryset(self):cate get_object_or_404(Category, pkself.kwargs.get(pk))return super(CategoryView, self).get_queryset().filter(categorycate)注意
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, pkself.kwargs.get(pk))return super(CategoryView, self).get_queryset().filter(categorycate)接下俩在 URL 配置中把 category 视图替换成类视图 CategoryView
文件位置blog/urls.py
app_name blog
urlpatterns [...path(categories/int:pk/, views.CategoryView.as_view(), namecategory),
]4.将 archive 视图函数改写成类视图
文件位置blog/views.py
原视图函数如下
def archive(request, year, month):定义 归档 视图post_list Post.objects.filter(created_time__yearyear,created_time__monthmonth)#.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__yearyear, created_time__monthmonth)接下俩在 URL 配置中把 archive 视图替换成类视图 ArchiveView
文件位置blog/urls.py
app_name blog
urlpatterns [...path(archives/int:year/int:month/, views.ArchiveView.as_view(), namearchive),
]5.将 tag 视图函数改写成类视图
文件位置blog/views.py
原视图函数如下
def tag(request, pk):# 记得在开始部分导入 Tag 类t get_object_or_404(Tag, pkpk)post_list Post.objects.filter(tagst)#.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, pkself.kwargs.get(pk))return super().get_queryset().filter(tagst)接下俩在 URL 配置中把 tag 视图替换成类视图 TagView
文件位置blog/urls.py
app_name blog
urlpatterns [...path(tags/int:pk/, views.TagView.as_view(), nametag),
]6.DetailView
除了从数据库中获取模型列表的数据外从数据库获取模型的一条记录数据也是常见的需求。
比如查看某篇文章的详情就是从数据库中获取这篇文章的记录然后渲染模板。
对于这种类型的需求django 提供了一个 DetailView 类视图。
7.将DetailView视图函数改写成类视图
接下俩将 detail 视图函数转换为等价的类视图 PostDetailView视图
文件位置blog/views.py
原视图函数如下
def detail(request, pk):定义文章详情页视图post get_object_or_404(Post, pkpk)#阅读量1post.increase_views()md markdown.Markdown(extensions[markdown.extensions.extra,markdown.extensions.codehilite,# markdown.extensions.toc,# 记得在顶部引入 TocExtension 和 slugifyTocExtension(slugifyslugify),])post.body md.convert(post.body)m re.search(rdiv classtoc\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.htmlcontext_object_name postdef 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, querysetNone):# 覆写 get_object 方法的目的是因为需要对 post 的 body 值进行渲染post super().get_object(querysetNone)md markdown.Markdown(extensions[markdown.extensions.extra,markdown.extensions.codehilite,# 记得在顶部引入 TocExtension 和 slugifyTocExtension(slugifyslugify),])post.body md.convert(post.body)m re.search(rdiv classtoc\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 解析。
4get 方法看成是 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),
]