# 第三節: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