django通用视图(CBV)
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)相关推荐
- django通用视图(视图类)的login登陆、权限限定
django的登陆限定和权限限定是view设计中很重要的一个组成.网上的教程大部分都是通过使用view函数的装饰器来实现,比如: @login_required(login_url='/') @per ...
- Django类视图CBV扩展基类之通用显示视图ListView、DetailView
前言 这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题 于是乎,我自己开发了一款面试宝典,希 ...
- Django通用视图ListView、DetailView、BaseListView使用方法
DetailView django.views.generic.detail.DetailView 在执行此视图时,self.object将包含该视图所操作的对象. 该视图从以下视图继承方法和属性: ...
- django通用视图的DetailView
SingleObjectMixin 主要功能: def get_queryset(self):返回query_set里的所有对象 如果提供的queryset为空且model不为空,返回self.mod ...
- Python Django CBV下的通用视图函数
ListView TemplateView DetailView 之前的代码实例基本上都是基于FBV的模式来撰写的,好处么,当然就是简单粗暴..正如: def index(request):retur ...
- Django 2.1.3 视图层 内置CBV通用视图
内置的基于类的通用视图 1. 扩展通用视图 2. 对象的通用视图 3. 制作"友好"的模板上下文 4. 添加额外的上下文 5. 查看对象的子集 6. 动态过滤 7. 执行额外的工作 ...
- Django 实现HTML转PDF 用通用视图编写PDF 并且让PDF支持中文
Django 实现HTML转PDF 用通用视图编写PDF 并且让PDF支持中文 如何使用django-easy-pdf django-easy-pdf的依赖 安装django-easy-pdf 使用过 ...
- django.views.generic通用视图的CreateView, ListView, UpdateView, DetailView, DeleteView用法
导入: from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView 入坑指南 用 ...
- django 1.8 官方文档翻译: 3-4-2 基于类的内建通用视图
基于类的内建通用视图 编写Web应用可能是单调的,因为你需要不断的重复某一种模式. Django尝试从model和 template层移除一些单调的情况,但是Web开发者依然会在view(视图)层经历 ...
最新文章
- 第14、15週PTA題目的處理
- 如果要和外国人做项目,加入一个teams是第一步,就跟我们的企业微信,钉钉差不多
- dods 机器人_胜利之日机器人补丁
- scala 数组合并_Scala程序合并两个数组或数组缓冲区
- [SDOI2006]二进制方程 并查集
- 共享充电宝“脱贫”:打脸王思聪 眼红了“负翁”ofo
- 使用Vanilla.js构建单页应用程序(SPA)网站
- Spring笔记2——Spring中Bean的装配
- SpringMVC 快速入门
- 3个查看远端端口是否畅通的方法
- 散列:散列函数与散列表(hash table)
- GIMP 教程:如何在 GIMP 中创建曲线文本
- SQL_SERVER_2008升级SQL_SERVER_2008_R2的方法
- js读取剪切板html,JS获取剪贴板的内容
- 投简历 找工作 App
- lbj学习日记 05 一维数组和二维数组
- 杜绝不良信息侵害未成年,皮皮APP发起语音社交行业自律书
- pygame精灵组有哪些方法_pygame 的精灵使用
- Mac开发利器之程序员编辑器MacVim学习总结(转)
- 手机计算机怎么恢复出厂设置密码,手机开机密码忘了怎么解锁
热门文章
- STOpen硬件设计4-周边模块设计二(CAN+RS485+UART+IO扩展等)
- JAVA:事件监听器之Button类中的addActionListener(ActionListener l)方法
- 变量的定义以及数据类型
- python红楼梦词云_用Python读红楼梦之——二、词云美化
- HDU-6555-The Fool(整除分块)
- 双亲委派模型是什么?
- 让你的 CDN 费用省 50% 以上!图片瘦身的正确姿势
- 精准医学中的深度学习和影像组学
- RF 电路设计中的常见问题及解决方案
- 服务器运维的工作内容及职责