291 lines
9.4 KiB
Markdown
291 lines
9.4 KiB
Markdown
<!-- {% raw %} -->
|
||
# 14.3 表單及驗證支援
|
||
在 Web 開發中對於這樣的一個流程可能很眼熟:
|
||
|
||
- 開啟一個網頁顯示出表單。
|
||
- 使用者填寫並提交了表單。
|
||
- 如果使用者提交了一些無效的資訊,或者可能漏掉了一個必填項,表單將會連同使用者的資料和錯誤問題的描述資訊回傳。
|
||
- 使用者再次填寫,繼續上一步過程,直到提交了一個有效的表單。
|
||
|
||
在接收端,指令碼必須:
|
||
|
||
- 檢查使用者提交的表單資料。
|
||
- 驗證資料是否為正確的型別,合適的標準。例如,如果一個使用者名稱被提交,它必須被驗證是否只包含了允許的字元。它必須有一個最小長度,不能超過最大長度。使用者名稱不能與已存在的他人使用者名稱重複,甚至是一個保留字等。
|
||
- 過濾資料並清理不安全字元,保證邏輯處理中接收的資料是安全的。
|
||
- 如果需要,預格式化資料(資料需要清除空白或者經過 HTML 編碼等等。)
|
||
- 準備好資料,插入資料庫。
|
||
|
||
儘管上面的過程並不是很複雜,但是通常情況下需要編寫很多程式碼,而且為了顯示錯誤資訊,在網頁中經常要使用多種不同的控制結構。建立表單驗證雖簡單,實施起來實在枯燥無味。
|
||
|
||
## 表單和驗證
|
||
對於開發者來說,一般開發過程都是相當複雜,而且大多是在重複一樣的工作。假設一個場景專案中忽然需要增加一個表單資料,那麼區域性程式碼的整個流程都需要修改。我們知道 Go 裡面 struct 是常用的一個數據結構,因此 beego 的 form 採用了 struct 來處理表單資訊。
|
||
|
||
首先定義一個開發 Web 應用時相對應的 struct,一個欄位對應一個 form 元素,透過 struct 的 tag 來定義相應的元素資訊和驗證資訊,如下所示:
|
||
|
||
```Go
|
||
|
||
type User struct{
|
||
Username string `form:text,valid:required`
|
||
Nickname string `form:text,valid:required`
|
||
Age int `form:text,valid:required|numeric`
|
||
Email string `form:text,valid:required|valid_email`
|
||
Introduce string `form:textarea`
|
||
}
|
||
```
|
||
定義好 struct 之後接下來在 controller 中這樣操作
|
||
|
||
```Go
|
||
|
||
func (this *AddController) Get() {
|
||
this.Data["form"] = beego.Form(&User{})
|
||
this.Layout = "admin/layout.html"
|
||
this.TplNames = "admin/add.tpl"
|
||
}
|
||
```
|
||
在範本中這樣顯示錶單
|
||
```html
|
||
|
||
<h1>New Blog Post</h1>
|
||
<form action="" method="post">
|
||
{{.form.render()}}
|
||
</form>
|
||
```
|
||
上面我們定義好了整個的第一步,從 struct 到顯示錶單的過程,接下來就是使用者填寫資訊,伺服器端接收資料然後驗證,最後插入資料庫。
|
||
|
||
```Go
|
||
|
||
func (this *AddController) Post() {
|
||
var user User
|
||
form := this.GetInput(&user)
|
||
if !form.Validates() {
|
||
return
|
||
}
|
||
models.UserInsert(&user)
|
||
this.Ctx.Redirect(302, "/admin/index")
|
||
}
|
||
```
|
||
## 表單型別
|
||
以下列表列出來了對應的 form 元素資訊:
|
||
<table cellpadding="0" cellspacing="1" border="0" style="width:100%" class="tableborder">
|
||
<tbody><tr>
|
||
<th>名稱</th>
|
||
<th>參數</th>
|
||
<th>功能描述</th>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>text</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">textbox 輸入框</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>button</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">按鈕</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>checkbox</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">多選擇框</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>dropdown</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">下拉選擇框</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>file</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">檔案上傳</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>hidden</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">隱藏元素</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>password</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">密碼輸入框</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>radio</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">單選框</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>textarea</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">文字輸入框</td>
|
||
</tr>
|
||
|
||
</tbody></table>
|
||
|
||
|
||
## 表單驗證
|
||
以下列表將列出可被使用的原生規則
|
||
<table cellpadding="0" cellspacing="1" border="0" style="width:100%" class="tableborder">
|
||
<tbody><tr>
|
||
<th>規則</th>
|
||
<th>參數</th>
|
||
<th>描述</th>
|
||
<th>舉例</th>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>required</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果元素為空,則回傳 FALSE</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>matches</strong></td>
|
||
<td class="td">Yes</td>
|
||
<td class="td">如果表單元素的值與參數中對應的表單欄位的值不相等,則回傳 FALSE</td>
|
||
<td class="td">matches[form_item]</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>is_unique</strong></td>
|
||
<td class="td">Yes</td>
|
||
<td class="td">如果表單元素的值與指定資料表欄位有重複,則回傳 False(譯者注:比如 is_unique[User.Email],那麼驗證類別會去查詢 User 表中 Email 欄位有沒有與表單元素一樣的值,如存重複,則回傳 false,這樣開發者就不必另寫 Callback 驗證程式碼。)</td>
|
||
<td class="td">is_unique[table.field]</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>min_length</strong></td>
|
||
<td class="td">Yes</td>
|
||
<td class="td">如果表單元素值的字元長度少於參數中定義的數字,則回傳 FALSE</td>
|
||
<td class="td">min_length[6]</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>max_length</strong></td>
|
||
<td class="td">Yes</td>
|
||
<td class="td">如果表單元素值的字元長度大於參數中定義的數字,則回傳 FALSE</td>
|
||
<td class="td">max_length[12]</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>exact_length</strong></td>
|
||
<td class="td">Yes</td>
|
||
<td class="td">如果表單元素值的字元長度與參數中定義的數字不符,則回傳 FALSE</td>
|
||
<td class="td">exact_length[8]</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>greater_than</strong></td>
|
||
<td class="td">Yes</td>
|
||
<td class="td">如果表單元素值是非數字型別,或小於參數定義的值,則回傳 FALSE</td>
|
||
<td class="td">greater_than[8]</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>less_than</strong></td>
|
||
<td class="td">Yes</td>
|
||
<td class="td">如果表單元素值是非數字型別,或大於參數定義的值,則回傳 FALSE</td>
|
||
<td class="td">less_than[8]</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>alpha</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素值中包含除字母以外的其他字元,則回傳 FALSE</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>alpha_numeric</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素值中包含除字母和數字以外的其他字元,則回傳 FALSE</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>alpha_dash</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素值中包含除字母/數字/下劃線/破折號以外的其他字元,則回傳 FALSE</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>numeric</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素值中包含除數字以外的字元,則回傳 FALSE</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>integer</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素中包含除整數以外的字元,則回傳 FALSE</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>decimal</strong></td>
|
||
<td class="td">Yes</td>
|
||
<td class="td">如果表單元素中輸入(非小數)不完整的值,則回傳 FALSE</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>is_natural</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素值中包含了非自然數的其他數值 (其他數值不包括零),則回傳 FALSE。自然數形如:0,1,2,3....等等。</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>is_natural_no_zero</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素值包含了非自然數的其他數值 (其他數值包括零),則回傳 FALSE。非零的自然數:1,2,3.....等等。</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>valid_email</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素值包含不合法的 email 地址,則回傳 FALSE</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>valid_emails</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素值中任何一個值包含不合法的 email 地址(地址之間用英文逗號分割),則回傳 FALSE。</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>valid_ip</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素的值不是一個合法的 IP 地址,則回傳 FALSE。</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="td"><strong>valid_base64</strong></td>
|
||
<td class="td">No</td>
|
||
<td class="td">如果表單元素的值包含除了 base64 編碼字元之外的其他字元,則回傳 FALSE。</td>
|
||
<td class="td"> </td>
|
||
</tr>
|
||
|
||
</tbody></table>
|
||
|
||
|
||
## links
|
||
* [目錄](<preface.md>)
|
||
* 上一節:[Session 支援](<14.2.md>)
|
||
* 下一節:[使用者認證](<14.4.md>)
|
||
<!-- {% endraw %} -->
|