# 第三节:ModelForm
# ModelForm:
大家在写表单的时候,会发现表单中的`Field`和模型中的`Field`基本上是一模一样的,而且表单中需要验证的数据,也就是我们模型中需要保存的。那么这时候我们就可以将模型中的字段和表单中的字段进行绑定。
比如现在有个`Article`的模型。示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models
<span class="hljs-keyword">from</span> django.core <span class="hljs-keyword">import</span> validators
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Article</span><span class="hljs-params">(models.Model)</span>:</span>
title = models.CharField(max_length=<span class="hljs-params">10</span>,validators=[validators.MinLengthValidator(limit_value=<span class="hljs-params">3</span>)])
content = models.TextField()
author = models.CharField(max_length=<span class="hljs-params">100</span>)
category = models.CharField(max_length=<span class="hljs-params">100</span>)
create_time = models.DateTimeField(auto_now_add=<span class="hljs-keyword">True</span>)
```
```
那么在写表单的时候,就不需要把`Article`模型中所有的字段都一个个重复写一遍了。示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-keyword">from</span> django <span class="hljs-keyword">import</span> forms
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyForm</span><span class="hljs-params">(forms.ModelForm)</span>:</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
model = Article
fields = <span class="hljs-string">"__all__"</span>
```
```
`MyForm`是继承自`forms.ModelForm`,然后在表单中定义了一个`Meta`类,在`Meta`类中指定了`model=Article`,以及`fields="__all__"`,这样就可以将`Article`模型中所有的字段都复制过来,进行验证。如果只想针对其中几个字段进行验证,那么可以给`fields`指定一个列表,将需要的字段写进去。比如只想验证`title`和`content`,那么可以使用以下代码实现:
```
<pre class="calibre12">```
<span class="hljs-keyword">from</span> django <span class="hljs-keyword">import</span> forms
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyForm</span><span class="hljs-params">(forms.ModelForm)</span>:</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
model = Article
fields = [<span class="hljs-string">'title'</span>,<span class="hljs-string">'content'</span>]
```
```
如果要验证的字段比较多,只是除了少数几个字段不需要验证,那么可以使用`exclude`来代替`fields`。比如我不想验证`category`,那么示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyForm</span><span class="hljs-params">(forms.ModelForm)</span>:</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
model = Article
exclude = [<span class="hljs-string">'category'</span>]
```
```
## 自定义错误消息:
使用`ModelForm`,因为字段都不是在表单中定义的,而是在模型中定义的,因此一些错误消息无法在字段中定义。那么这时候可以在`Meta`类中,定义`error_messages`,然后把相应的错误消息写到里面去。示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyForm</span><span class="hljs-params">(forms.ModelForm)</span>:</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
model = Article
exclude = [<span class="hljs-string">'category'</span>]
error_messages ={
<span class="hljs-string">'title'</span>:{
<span class="hljs-string">'max_length'</span>: <span class="hljs-string">'最多不能超过10个字符!'</span>,
<span class="hljs-string">'min_length'</span>: <span class="hljs-string">'最少不能少于3个字符!'</span>
},
<span class="hljs-string">'content'</span>: {
<span class="hljs-string">'required'</span>: <span class="hljs-string">'必须输入content!'</span>,
}
}
```
```
## save方法:
`ModelForm`还有`save`方法,可以在验证完成后直接调用`save`方法,就可以将这个数据保存到数据库中了。示例代码如下:
```
<pre class="calibre12">```
form = MyForm(request.POST)
<span class="hljs-keyword">if</span> form.is_valid():
form.save()
<span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'succes'</span>)
<span class="hljs-keyword">else</span>:
print(form.get_errors())
<span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'fail'</span>)
```
```
这个方法必须要在`clean`没有问题后才能使用,如果在`clean`之前使用,会抛出异常。另外,我们在调用`save`方法的时候,如果传入一个`commit=False`,那么只会生成这个模型的对象,而不会把这个对象真正的插入到数据库中。比如表单上验证的字段没有包含模型中所有的字段,这时候就可以先创建对象,再根据填充其他字段,把所有字段的值都补充完成后,再保存到数据库中。示例代码如下:
```
<pre class="calibre12">```
form = MyForm(request.POST)
<span class="hljs-keyword">if</span> form.is_valid():
article = form.save(commit=<span class="hljs-keyword">False</span>)
article.category = <span class="hljs-string">'Python'</span>
article.save()
<span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'succes'</span>)
<span class="hljs-keyword">else</span>:
print(form.get_errors())
<span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'fail'</span>)
```
```
- Introduction
- 第一章:学前准备
- 第一节:虚拟环境
- 第二节:准备工作
- 第三节:Django介绍
- 第四节:URL组成部分
- 第二章:URL与视图
- 第一节:第一个Django项目
- 第二节:视图与URL分发器
- 第三章:模板
- 第一节:模板介绍
- 第二节:模板变量
- 第三节:常用标签
- 第四节:常用过滤器
- 第五节:自定义过滤器
- 第七节:模版结构优化
- 第八节:加载静态文件
- 第四章:数据库
- 第一节:MySQL相关软件
- 第二节:数据库操作
- 第三节:ORM模型
- 第四节:模型常用字段
- 第五节:外键和表关系
- 第六节:增删改查操作
- 第七节:查询操作
- 第八节:QuerySet API
- 第九节:ORM模型迁移
- 第十节:ORM作业
- 第十一节:ORM作业参考答案
- 第十二节:Pycharm连接数据库
- 第五章:视图高级
- 第一节:限制请求method
- 第二节:页面重定向
- 第三节:HttpRequest对象
- 第四节:HttpResponse对象
- 第五节:生成CSV文件
- 第六节:类视图
- 第七节:错误处理
- 第六章:表单
- 第一节:表单概述
- 第二节:用表单验证数据
- 第三节:ModelForm
- 第四节:文件上传
- 第七章:cookie和session
- 第八章:上下文处理器和中间件
- 第一节:上下文处理器
- 第二节:中间件
- 第九章:安全
- 第一节:CSRF攻击
- 第二节:XSS攻击
- 第三节:点击劫持攻击
- 第四节:SQL注入
- 第十章:信号
- 第一节:什么是信号
- 第十一章:验证和授权
- 第一节:概述
- 第二节:用户对象
- 第三节:权限和分组
- 第十二章:Admin系统
- 第十三章:Django的缓存
- 第十四章:memcached
- 第十五章:Redis