1. 介绍

Django提供了很多通用的基于类的视图(Class Based View),来帮我们简化视图的编写。这些View与上述操作的对应关系如下:

  • 展示对象列表(比如所有用户,所有文章)- ListView

  • 展示某个对象的详细信息(比如用户资料,比如文章详情) - DetailView

  • 通过表单创建某个对象(比如创建用户,新建文章)- CreateView

  • 通过表单更新某个对象信息(比如修改密码,修改文字内容)- UpdateView

  • 用户填写表单后转到某个完成页面 - FormView

  • 删除某个对象 - DeleteView

上述常用通用视图一共有6个,前2个属于展示类视图(Display view), 后面4个属于编辑类视图(Edit view)。下面我们就来看下这些通用视图是如何工作的,如何简化我们代码的。一旦你用上通用视图,你就会爱上她。

重要:如果你要使用Edit view,请务必在模型models里定义get_absolute_url()方法,否则会出现错误。这是因为通用视图在对一个对象完成编辑后,需要一个返回链接。

Django通用视图之ListView

介绍

ListView用来展示一个对象的列表。它只需要一个参数模型名称即可。比如我们希望展示所有文章列表,

我们的views.py可以简化为:

尽管我们只写了一行model = Article, ListView实际上在背后做了很多事情:

  • 提取了需要显示的对象列表或数据集queryset: Article.objects.all()

  • 指定了用来显示对象列表的模板名称(template name): 默认app_name/model_name_list.html, 即blog/article_list.html.

  • 指定了内容对象名称(context object name):默认值object_list

 Create your views here.
from django.views.generic import ListView
from .models import Articleclass IndexView(ListView):model = Article

上述代码等同于:

# 展示所有文章
def index(request):queryset = Article.objects.all()return render(request, 'blog/article_list.html', {"object_list": queryset})

ListView的自定义

介绍

你或许已经注意到了2个问题:需要显示的文章对象列表并没有按发布时间逆序排列,内容对象名称object_list也不友好。

或许你也不喜欢默认的模板名字,还希望通过这个视图给模板传递额外的内容(比如现在的时间)。

你可以轻易地通过重写queryset, template_name和context_object_name来完成ListView的自定义。

如果你还需要传递模型以外的内容,比如现在的时间,你还可以通过重写get_context_data方法传递额外的参数或内容。

代码

# Create your views here.
from django.views.generic import ListView
from .models import Article
from django.utils import timezoneclass IndexView(ListView):queryset = Article.objects.all().order_by("-pub_date")template_name = 'blog/article_list.html'# 传递到html的变量名称context_object_name = 'latest_articles'def get_context_data(self, **kwargs):context = super().get_context_data(**kwargs)context['now'] = timezone.now()return context

queryset还不能满足你的要求

比如你希望一个用户只看到自己发表的文章清单,你可以通过更具体的get_queryset方法来返回一个需要显示的对象列表。

# Create your views here.
from django.views.generic import ListView
from .models import Article
from django.utils import timezoneclass IndexView(ListView):template_name = 'blog/article_list.html'context_object_name = 'latest_articles'def get_queryset(self):return Article.objects.filter(author=self.request.user).order_by('-pub_date')def get_context_data(self, **kwargs):context = super().get_context_data(**kwargs)context['now'] = timezone.now()return context

urls.py

目前urls.py里path和re_path都只能指向视图view里的一个函数或方法,而不能指向一个基于类的视图(Class Based View)。

Django提供了一个额外as_view()方法,可以将一个类伪装成方法。这点在当你使用Django在带的view类或自定义的类时候非常重要。

# blog/urls.py
from django.urls import path, re_pathfrom . import viewsurlpatterns = [path('blog/', views.IndexView.as_view(), name='index'),
]

Django通用视图之DetailView

介绍

DetailView用来展示一个具体对象的详细信息。它需要URL提供访问某个对象的具体参数(如pk, slug值)。本例中用来展示某篇文章详细内容的view可以简写为:

代码

DetailView默认的模板是app/model_name_detail.html,

默认的内容对象名字context_object_name是model_name。

本例中默认模板是blog/article_detail.html,

默认对象名字是article,

在模板里可通过 {{ article.title }}获取文章标题。

# Create your views here.
from django.views.generic import DetailView
from .models import Articleclass ArticleDetailView(DetailView):model = Article

自定义

你同样可以通过重写queryset, template_name和context_object_name来完成DetailView的自定义。

你还可以通过重写get_context_data方法传递额外的参数或内容。

如果你指定了queryset, 那么返回的object是queryset.get(pk = id), 而不是model.objects.get(pk = id)。

# Create your views here.
from django.views.generic import ListView,DetailView
from .models import Article
from django.utils import timezoneclass ArticleDetailView(DetailView):queryset = Article.objects.all().order_by("-pub_date") # template_name = 'blog/article_detail.html'context_object_name = 'article'def get_context_data(self, **kwargs):context = super().get_context_data(**kwargs)context['now'] = timezone.now()return context

get_object()

在实际应用中,上述代码可能还不能满足你的要求。比如你希望一个用户只能看到自己发表的文章详情。当用户查看别人的文章详情时,返回http 404错误。这时候你可以通过更具体的get_object()方法来返回一个更具体的对象。代码如下:

# Create your views here.
from django.views.generic import DetailView
from django.http import Http404
from .models import Article
from django.utils import timezoneclass ArticleDetailView(DetailView):queryset = Article.objects.all().order_by("-pub_date")template_name = 'blog/article_detail.html'context_object_name = 'article'def get_object(self, queryset=None):obj = super().get_object(queryset=queryset)if obj.author != self.request.user:raise Http404()return objdef get_context_data(self, **kwargs):context = super().get_context_data(**kwargs)context['now'] = timezone.now()return context

Django通用视图之CreateView

介绍

CreateView一般通过某个表单创建某个对象,通常完成后会转到对象列表。比如一个最简单的文章创建CreateView可以写成:

from django.views.generic.edit import CreateView
from .models import Articleclass ArticleCreateView(CreateView):model = Articlefields = ['title', 'body', 'pub_date']

默认的模板

CreateView默认的模板是model_name_form.html, 即article_form.html。默认的context_object_name是form。模板代码如下图所示:

# blog/article_form.html
<form method="post">{% csrf_token %}{{ form.as_p }}<input type="submit" value="Save" />
</form>

自定义

如果你不想使用默认的模板和默认的表单,你可以通过重写template_name和form_class来完成CreateView的自定义。虽然form_valid方法不是必需,但很有用。当用户提交的数据是有效的时候,你可以通过定义此方法做些别的事情,比如发送邮件,存取额外的数据。

from django.views.generic.edit import CreateView
from .models import Article
from .forms import ArticleCreateFormclass ArticleCreateView(CreateView):model = Articletemplate_name = 'blog/article_create_form.html'form_class = ArticleCreateFormdef form_valid(self, form):form.do_sth()return super().form_valid(form)

form_valid

form_valid方法一个常见用途就是就是将创建对象的用户与model里的user结合。见下面例子。

class ArticleCreateView(CreateView):model = Articletemplate_name = 'blog/article_create_form.html'form_class = ArticleCreateFormdef form_valid(self, form):form.instance.author = self.request.userreturn super().form_valid(form)

Django通用视图之UpdateView

介绍

UpdateView一般通过某个表单更新现有对象的信息,更新完成后会转到对象详细信息页面。它需要URL提供访问某个对象的具体参数(如pk, slug值)。比如一个最简单的文章更新的UpdateView如下所示。

from django.views.generic.edit import UpdateView
from .models import Articleclass ArticleUpdateView(UpdateView):model = Articlefields = ['title', 'body', 'pub_date']

默认模板

UpdateView和CreateView很类似,比如默认模板都是model_name_form.html。但是区别有两点:

  • CreateView显示的表单是空表单,UpdateView中的表单会显示现有对象的数据。

  • 用户提交表单后,CreateView转向对象列表,UpdateView转向对象详细信息页面。

自定义

你可以通过重写template_name和form_class来完成UpdateView的自定义。

  • 本例中默认的form是article_form.html, 你可以改为article_update_form.html。

  • 虽然form_valid方法不是必需,但很有用。当用户提交的数据是有效的时候,你可以通过定义此方法做些别的事情,比如发送邮件,存取额外的数据。

from django.views.generic.edit import UpdateView
from .models import Article
from .forms import ArticleUpdateFormclass ArticleUpdateView(UpdateView):model = Articletemplate_name = 'blog/article_update_form.html'form_class = ArticleUpdateFormdef form_valid(self, form):form.do_sth()return super().form_valid(form)

Django通用视图之FormView

FormView一般用来展示某个表单,而不是某个模型对象。

当用户输入信息未通过表单验证,显示错误信息。

当用户输入信息通过表单验证提交成功后,转到其它页面。

使用FormView一般需要定义template_name, form_class和跳转的success_url.

# views.py - Use FormView
from myapp.forms import ContactForm
from django.views.generic.edit import FormViewclass ContactView(FormView):template_name = 'contact.html'form_class = ContactFormsuccess_url = '/thanks/'def form_valid(self, form):# This method is called when valid form data has been POSTed.# It should return an HttpResponse.form.send_email()return super().form_valid(form)

Django通用视图之DeleteView

介绍

DeleteView一般用来删除某个具体对象。它要求用户点击确认后再删除一个对象。使用这个通用视图,你需要定义模型的名称model和成功删除对象后的返回的URL。默认模板是myapp/model_confirm_delete.html。默认内容对象名字是model_name,本例中为article。

本例使用了默认的模板blog/article_confirm_delete.html,删除文章后通过reverse_lazy方法返回到index页面。

from django.urls import reverse_lazy
from django.views.generic.edit import DeleteView
from .models import Articleclass ArticleDeleteView(DeleteView):model = Articlesuccess_url = reverse_lazy('index')

模板内容如下:

# blog/article_confirm_delete.html
<form method="post">{% csrf_token %}<p>Are you sure you want to delete "{{ article }}"?</p><input type="submit" value="Confirm" />
</form>

自定义

但这段代码还有个问题,你注意到没? 用户可以删除任意文章,包括别人发表的文章。如果我们想用户只能删除自己的文章,上述代码怎么改? 我们通过get_queryset方法筛选出作者自己的文章即可。views.py可改成下文:

from django.urls import reverse_lazy
from django.views.generic.edit import DeleteView
from .models import Articleclass ArticleDeleteView(DeleteView):model = Articlesuccess_url = reverse_lazy('index')def get_queryset(self):return self.model.objects.filter(author=self.request.user)

django通用视图(CBV)相关推荐

  1. django通用视图(视图类)的login登陆、权限限定

    django的登陆限定和权限限定是view设计中很重要的一个组成.网上的教程大部分都是通过使用view函数的装饰器来实现,比如: @login_required(login_url='/') @per ...

  2. Django类视图CBV扩展基类之通用显示视图ListView、DetailView

    前言 这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题 于是乎,我自己开发了一款面试宝典,希 ...

  3. Django通用视图ListView、DetailView、BaseListView使用方法

    DetailView django.views.generic.detail.DetailView 在执行此视图时,self.object将包含该视图所操作的对象. 该视图从以下视图继承方法和属性: ...

  4. django通用视图的DetailView

    SingleObjectMixin 主要功能: def get_queryset(self):返回query_set里的所有对象 如果提供的queryset为空且model不为空,返回self.mod ...

  5. Python Django CBV下的通用视图函数

    ListView TemplateView DetailView 之前的代码实例基本上都是基于FBV的模式来撰写的,好处么,当然就是简单粗暴..正如: def index(request):retur ...

  6. Django 2.1.3 视图层 内置CBV通用视图

    内置的基于类的通用视图 1. 扩展通用视图 2. 对象的通用视图 3. 制作"友好"的模板上下文 4. 添加额外的上下文 5. 查看对象的子集 6. 动态过滤 7. 执行额外的工作 ...

  7. Django 实现HTML转PDF 用通用视图编写PDF 并且让PDF支持中文

    Django 实现HTML转PDF 用通用视图编写PDF 并且让PDF支持中文 如何使用django-easy-pdf django-easy-pdf的依赖 安装django-easy-pdf 使用过 ...

  8. django.views.generic通用视图的CreateView, ListView, UpdateView, DetailView, DeleteView用法

    导入: from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView 入坑指南 用 ...

  9. django 1.8 官方文档翻译: 3-4-2 基于类的内建通用视图

    基于类的内建通用视图 编写Web应用可能是单调的,因为你需要不断的重复某一种模式. Django尝试从model和 template层移除一些单调的情况,但是Web开发者依然会在view(视图)层经历 ...

最新文章

  1. 第14、15週PTA題目的處理
  2. 如果要和外国人做项目,加入一个teams是第一步,就跟我们的企业微信,钉钉差不多
  3. dods 机器人_胜利之日机器人补丁
  4. scala 数组合并_Scala程序合并两个数组或数组缓冲区
  5. [SDOI2006]二进制方程 并查集
  6. 共享充电宝“脱贫”:打脸王思聪 眼红了“负翁”ofo
  7. 使用Vanilla.js构建单页应用程序(SPA)网站
  8. Spring笔记2——Spring中Bean的装配
  9. SpringMVC 快速入门
  10. 3个查看远端端口是否畅通的方法
  11. 散列:散列函数与散列表(hash table)
  12. GIMP 教程:如何在 GIMP 中创建曲线文本
  13. SQL_SERVER_2008升级SQL_SERVER_2008_R2的方法
  14. js读取剪切板html,JS获取剪贴板的内容
  15. 投简历 找工作 App
  16. lbj学习日记 05 一维数组和二维数组
  17. 杜绝不良信息侵害未成年,皮皮APP发起语音社交行业自律书
  18. pygame精灵组有哪些方法_pygame 的精灵使用
  19. Mac开发利器之程序员编辑器MacVim学习总结(转)
  20. 手机计算机怎么恢复出厂设置密码,手机开机密码忘了怎么解锁

热门文章

  1. STOpen硬件设计4-周边模块设计二(CAN+RS485+UART+IO扩展等)
  2. JAVA:事件监听器之Button类中的addActionListener(ActionListener l)方法
  3. 变量的定义以及数据类型
  4. python红楼梦词云_用Python读红楼梦之——二、词云美化
  5. HDU-6555-The Fool(整除分块)
  6. 双亲委派模型是什么?
  7. 让你的 CDN 费用省 50% 以上!图片瘦身的正确姿势
  8. 精准医学中的深度学习和影像组学
  9. RF 电路设计中的常见问题及解决方案
  10. 服务器运维的工作内容及职责