Django之通用视图组件
前面我们说到过Django之CBV,说到过Django的视图层,也说到过DRF视图组件使用,其中在DRF中提到过通用视图组件,刚开始不太明白,封装太多层了,直到后面看见Django自己的通用视图。
其实在Django的文档中,这部分内容还挺多了,我直接将所有类列在这里,大家有兴趣可以查看官方文档的介绍,我这里只说明常用的几种,做出这么多通用类无非是帮我们节省书写代码,看了下源码还是很容易懂的。
- 基础视图
- 通用显示视图
- 通用编辑视图
- 通用日期视图
- 基于类的视图混合
- 基于类的通用视图-扁平化索引
常用视图类
类名 | 功能 | 例子 |
---|---|---|
View | 基本View, 可以在任何时候使用 | 见后面详细介绍 |
RedirectView | 重新定向到其他URL | 将访问”/log-in/“的用户重新定向到”/login/“ |
TemplateView | 显示Django HTML template | 一般网站中使用模板显示的页 |
ListView | 显示对象列表 | 文章列表页 |
DetailView | 显示对象详情 | 文章详细页 |
FormView | 提交From | 网站联系我们或emai订阅form |
CreateView | 创建对象 | 创建新文章页 |
UpdateView | 更新对象 | 修改文章页 |
DeleteView | 删除对象 | 删除文章页 |
Generic date views | 显示一段时间内的对象 | 按时间归类的博客 |
ListView视图
表示对象列表的一个页面
属性
- model: 指定模型
- tempalta_name:模板文件
- queryset:指定一个经过过滤的对象列表,将取代
model
提供的值 - context_object_name: 指定要在上下文中使用的变量的名称(默认目标对象名为:object_list)
方法
- get_queryset():获取此视图的对象列表.必须是可迭代或者可以使查询集.默认返回
queryset
属性.可以通过重写该方法实现动态过滤.让这种方式能够工作的关键点,在于当类视图被调用时,各种有用的对象被存储在self
上,同request(self.request)
一样,其中包含了从URLconf中获取到的位置参数(self.args
)和关键字参数(self.kwargs
). - *get_context_data(kwargs)*: 返回显示对象的上下文数据,通过覆盖**该方法返回额外的上下文
例子
不指定模型显示列表
1 | class ArticleListView(ListView): |
模板调用
1 | <h1> |
指定模型显示列表
以下代码我们指定了它的模型对象,所以就没有必要在用get_queryset()去返回了,除非需要重新过滤数据。
1 | class ArticleListView(ListView): |
模板调用
视图中我们没有定义列表对象context_object_name,所以模板中默认要使用object_list。
1 | <h1> |
FormView视图
用于提交表单,其实这个就是CreateView和UpdateView的低配版,大概看了下源码,差别就是FromView提交表单验证通过后直接跳转到指定视图了,而后者则是执行了数据库添加或更新操作。
前提说下我们这里定义过了form组件类,所以别再疑惑我从哪儿来的ArticleForm类。
1 | class ArticleCreateView(FormView): |
模板
1 | <form method="post" novalidate> |
我这里使用的是bootcss,所以自定义了样式,如用默认样式,直接
1 | <form method="post">{% csrf_token %} |
CreateView视图
这个真的跟FormView差别不大,直接上例子吧。
1 | class ArticleCreateView(CreateView): |
CreateView中的form_valid已经帮我们把数据保存至数据库了,如果你不需要像我一样添加成功输出提示,那就完全没必要重写form_valid方法了。
注意:此处有坑
- success_url复制为跳转链接地址,可以直接字符串写链接地址,可以使用reverse_lazy()反向解析,但是直接使用reverse()会报错;
- form_class中定义的ArticleForm继承的是forms.ModelForm,如果直接继承forms.Form同样会报错,两处出错有兴趣的朋友可以自己查下原因哈。
后面在使用通用视图的时候感受到不是太灵便,索性还是自定义cbv吧。仁者见仁智者见智吧,喜欢用这种方式的参考如下详细的介绍。
详解通用视图
Class-based views是Django为解决建站过程中的常见的呈现模式而建立的。具有如下几个原则:
- 代码越少越好
- 永远不要重复代码
- View应当只包含呈现逻辑, 不应包括业务逻辑
- 保持view逻辑清晰简单
- 不要将CBVs用作403, 404, 500的错误处理程序
- 保持mixin简单明了
django自带的view如下表所示:
类名 | 功能 | 例子 |
---|---|---|
View | 基本View, 可以在任何时候使用 | 见后面详细介绍 |
RedirectView | 重新定向到其他URL | 将访问”/log-in/“的用户重新定向到”/login/“ |
TemplateView | 显示Django HTML template | 一般网站中使用模板显示的页 |
ListView | 显示对象列表 | 文章列表页 |
DetailView | 显示对象详情 | 文章详细页 |
FormView | 提交From | 网站联系我们或emai订阅form |
CreateView | 创建对象 | 创建新文章页 |
UpdateView | 更新对象 | 修改文章页 |
DeleteView | 删除对象 | 删除文章页 |
Generic date views | 显示一段时间内的对象 | 按时间归类的博客 |
ListView
表示对象列表的一个页面.
执行这个视图的时候,self.object_list
将包含视图正在操作的对象列表(通常是一个查询集,但不是必须).
属性:
- model: 指定模型
- tempalta_name:模板文件
- queryset:指定一个经过过滤的对象列表,将取代
model
提供的值 - context_object_name: 指定要在上下文中使用的变量的名称
方法:
- get_queryset():获取此视图的对象列表.必须是可迭代或者可以使查询集.默认返回
queryset
属性.可以通过重写该方法实现动态过滤.让这种方式能够工作的关键点,在于当类视图被调用时,各种有用的对象被存储在self
上,同request(self.request)
一样,其中包含了从URLconf中获取到的位置参数(self.args
)和关键字参数(self.kwargs
). - *get_context_data(kwargs)*: 返回显示对象的上下文数据,通过覆盖**该方法返回额外的上下文
DetailView
执行这个视图的时候,self.object
将包含视图正在操作的对象.
属性:
- model: 视图要显示的模型
- queryset: 表示对象的一个查询集.
queryset
的值优先于model
的值. - template_name: 字符串表示的模板名称.
- context_object_name: 指定在上下文中使用的变量的名称.
- pk_url_kwarg: URLconf中,包含逐渐的关键字参数的名称.默认为’pk’.
- get_context_data:返回显示对象的上下文数据.
方法:
- get_queryset():返回用来获取本视图显示对象的
queryset
.如果设置了queryset
属性,get_queryset()
默认返回它的值. - get_object(queryset=None):返回该视图要显示的单个对象.如果提供了
queryset
,该queryset
将作为对象的查询源,否则,将使用get_queryset()
.get_object()
从视图的所有参数中查找pk_url_kwarg
参数,如果找到了这个参数,该方法使用这个参数的值执行一个基于逐渐的查询.如果这个参数没有找到,该方法查找slug_url_kwarg
参数,使用slug_field
字段执行针对slug的查询.当query_pk_and_slug
为True
时,get_object()
将使用主键和slug执行查询. - *get_context_data(*kwargs):返回显示对象的上下文数据.这个方法的基本实现需要
object
属性被视图赋值(即使是None).它返回一个包含这些内容的字典:
object
:这个视图显示的对象(self.object
)
context_object_name
:self.object
也将存储在get_context_object_name()
返回的名称中,该名称默认为模型的小写名称.
FormView
显示表单的视图,验证错误时,重新显示表单并显示错误信息;成功时,重定向到一个新的URL.
属性:
*form_class:*要实例化的Form类.
*success_url:*表单成功处理后重定向到的URL.
*tamplate_name:*字符串表示的模板名称.
方法:
*get_success_url():*决定在表单成功验证后重定向到的URL,默认返回
success_url
.*form_valid(form):*在表单验证成功后调用该方法(注意并没有对数据进行操作,例如保存!),并重定向到
get_success_url()
,可以覆盖该方法在以上行为之间添加额外的动作.该方法必须返回一个HttpResponse
.*form_invalid(form):*如果表单验证失败,则使用已填充的表单数据和错误信息重新渲染上下文.
*get_context_data(**kwargs):*返回显示对象的上下文数据.
CreateView
显示用于创建对象的表单的视图,通过验证错误信息重新显示视图,并且保存对象.
属性:
tamplate_name:
form_class:
*fields:*字段名称列表,其解释方式与ModelForm
的Meta.fields
相同.如果你是自动生成表单类,那么该属性不能省略.
success_url:
model:
queryset:
context_object_name:
pk_url_kwarg:
方法:
get_queryset():
get_object():
form_valid():
*get_context_data(*kwargs):
(未填写属性和方法的使用同上)
UpdateView
显示用于编辑现有对象的表单的视图,重新显示具有验证错误信息的视图,并且保存对象.这里使用从对象模型自动生成的表单(除非手动制定表单类).
该视图用法与CreateView基本相同,仅在BaseUpdateView中对get()
和post()
的内部实现有区别.
DeleteView
显示确认页面并删除现有对象的视图.仅当请求方法为POST时,才会删除给定的内容.如果此视图是通过GET提取的,它将显示一个确认页面,其中包含POST到同一网址的表单.
属性:
tamplate_name:
success_url:
model:
queryset:
context_object_name:
pk_url_kwarg:
*方法:
get_object():
get_queryset():
*get_context_data(*kwargs):
delete(request, args, **kwargs):*在获取到的对象上调用
delete()
方法,然后重定向到success_url
.
实例
1、创建django工程,创建名为crud的app,此处略过
2、 修改models.py
1 | class employee(models.Model): |
3、配置
1 | INSTALLED_APPS = [ |
4、数据迁移
1 | python manage.py makemigrations crud |
5、修改urls,views
crud中的urls
1 | from django.conf.urls import url |
工程中urls
1 | from django.conf.urls import url, include |
1 | # -*- coding: utf-8 -*- |
6、新建模板
employee_list.html
1 | <ul> |
employee_form.html
1 | <title>Title</title> |
employee_confirm_delete.html
1 | <form method="post">{% csrf_token %} |
employee_detail.html
1 | <h1>你好,{{ object.name }}</h1> |
7、启动服务python manage.py runserver
浏览器中输入 http://127.0.0.1:8000/crud/ 即可对员工进行增加、删除、修改
—–UpdateView和CreateView—–
我们有了Project和Schedule列表显示后,现在需要添加新增和修改的操作。可以直接用Django通用视图里的UpdateView和CreateView。根据官网文档的例子,我们先在projtrack/views.py中添加项目新增和修改视图的代码:
1 | # projtrack/views.py |
因为编辑和新增页面的前端代码基本一样,我们在这里都指定了template为update_form。也可指定不同的模板。另外也可用template_name_suffix参数去指定模板。比如,如果设定template_name_suffix = ‘_create_form’, 则用到的模板将会是projtrack/project_create_form.html。
这里projtrack/update_form.html代码如下:
1 | {% extends "projtrack/index.html" %} |
1 | <p> |
其它form在模版中的渲染方式还包括:
form.as_ul:渲染表单为一系列的li标签,每个li 标签包含一个字段
form.as_table:输出表单为一个HTML的table。
for field in form:通过迭代form,获取其中的所有field。field可引用的包括: , , 。输出为field的label元素,输出为field的input,为field的errors元素(errors一般在form验证出错的时候显示)。
form.fieldname:直接将form作为一个dict,引用其每一个field,比如 引用form中的title这个field。这种方式一般用于form需要更加精准的样式的时候,逐个元素逐个元素的编排到html中。
完成后可在页面上新增或修改项目信息。不过点击Update后会有一个报错:191989-055d8b7a362f2603.png
意思是新增后修改完成后我们没有定义一个redirect的url去跳转。根据报错的提示,我们可以直接在视图下给success_url参数赋值,或在模型中去定义get_absolute_url()方法,去设置成功后跳转的url。这里我们在模型中添加:
1 | # projtrack/model.py |
这样,在新增或修改项目成功就就跳转到项目列表页面