在Web开发中对于这样的一个流程可能很眼熟:
* 打开一个网页显示出表单。
* 用户填写并提交了表单。
* 如果用户提交了一些无效的信息,或者可能漏掉了一个必填项,表单将会连同用户的数据和错误问题的描述信息返回。
* 用户再次填写,继续上一步过程,直到提交了一个有效的表单。
在接收端,脚本必须:
* 检查用户递交的表单数据。
* 验证数据是否为正确的类型,合适的标准。例如,如果一个用户名被提交,它必须被验证是否只包含了允许的字符。它必须有一个最小长度,不能超过最大长度。用户名不能与已存在的他人用户名重复,甚至是一个保留字等。
* 过滤数据并清理不安全字符,保证逻辑处理中接收的数据是安全的。
* 如果需要,预格式化数据(数据需要清除空白或者经过HTML编码等等。)
* 准备好数据,插入数据库。
尽管上面的过程并不是很复杂,但是通常情况下需要编写很多代码,而且为了显示错误信息,在网页中经常要使用多种不同的控制结构。创建表单验证虽简单,实施起来实在枯燥无味。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/14.3.md#表单和验证)表单和验证
对于开发者来说,一般开发过程都是相当复杂,而且大多是在重复一样的工作。假设一个场景项目中忽然需要增加一个表单数据,那么局部代码的整个流程都需要修改。我们知道Go里面struct是常用的一个数据结构,因此beego的form采用了struct来处理表单信息。
首先定义一个开发Web应用时相对应的struct,一个字段对应一个form元素,通过struct的tag来定义相应的元素信息和验证信息,如下所示:
~~~
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中这样操作
~~~
func (this *AddController) Get() {
this.Data["form"] = beego.Form(&User{})
this.Layout = "admin/layout.html"
this.TplNames = "admin/add.tpl"
}
~~~
在模板中这样显示表单
~~~
<h1>New Blog Post</h1>
<form action="" method="post">
{{.form.render()}}
</form>
~~~
上面我们定义好了整个的第一步,从struct到显示表单的过程,接下来就是用户填写信息,服务器端接收数据然后验证,最后插入数据库。
~~~
func (this *AddController) Post() {
var user User
form := this.GetInput(&user)
if !form.Validates() {
return
}
models.UserInsert(&user)
this.Ctx.Redirect(302, "/admin/index")
}
~~~
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/14.3.md#表单类型)表单类型
以下列表列出来了对应的form元素信息:
| 名称 | 参数 | 功能描述 |
|-----|------|--------|
| **text** | No | textbox输入框 |
| **button** | No | 按钮 |
| **checkbox** | No | 多选择框 |
| **dropdown** | No | 下拉选择框 |
| **file** | No | 文件上传 |
| **hidden** | No | 隐藏元素 |
| **password** | No | 密码输入框 |
| **radio** | No | 单选框 |
| **textarea** | No | 文本输入框 |
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/14.3.md#表单验证)表单验证
以下列表将列出可被使用的原生规则
| 规则 | 参数 | 描述 | 举例 |
|-----|------|--------|--------|
| **required** | No | 如果元素为空,则返回FALSE |
| **matches** | Yes | 如果表单元素的值与参数中对应的表单字段的值不相等,则返回FALSE | matches[form_item] |
| **is_unique** | Yes | 如果表单元素的值与指定数据表栏位有重复,则返回False(译者注:比如is_unique[User.Email],那么验证类会去查找User表中Email栏位有没有与表单元素一样的值,如存重复,则返回false,这样开发者就不必另写Callback验证代码。) | is_unique[table.field] |
| **min_length** | Yes | 如果表单元素值的字符长度少于参数中定义的数字,则返回FALSE | min_length[6] |
| **max_length** | Yes | 如果表单元素值的字符长度大于参数中定义的数字,则返回FALSE | max_length[12] |
| **exact_length** | Yes | 如果表单元素值的字符长度与参数中定义的数字不符,则返回FALSE | exact_length[8] |
| **greater_than** | Yes | 如果表单元素值是非数字类型,或小于参数定义的值,则返回FALSE | greater_than[8] |
| **less_than** | Yes | 如果表单元素值是非数字类型,或大于参数定义的值,则返回FALSE | less_than[8] |
| **alpha** | No | 如果表单元素值中包含除字母以外的其他字符,则返回FALSE ||
| **alpha_numeric** | No | 如果表单元素值中包含除字母和数字以外的其他字符,则返回FALSE ||
| **alpha_dash** | No | 如果表单元素值中包含除字母/数字/下划线/破折号以外的其他字符,则返回FALSE ||
| **numeric** | No | 如果表单元素值中包含除数字以外的字符,则返回 FALSE ||
| **integer** | No | 如果表单元素中包含除整数以外的字符,则返回FALSE ||
| **decimal** | Yes | 如果表单元素中输入(非小数)不完整的值,则返回FALSE ||
| **is_natural** | No | 如果表单元素值中包含了非自然数的其他数值 (其他数值不包括零),则返回FALSE。自然数形如:0,1,2,3....等等。 ||
| **is_natural_no_zero** | No | 如果表单元素值包含了非自然数的其他数值 (其他数值包括零),则返回FALSE。非零的自然数:1,2,3.....等等。 ||
| **valid_email** | No | 如果表单元素值包含不合法的email地址,则返回FALSE ||
| **valid_emails** | No | 如果表单元素值中任何一个值包含不合法的email地址(地址之间用英文逗号分割),则返回FALSE。 ||
| **valid_ip** | No | 如果表单元素的值不是一个合法的IP地址,则返回FALSE。 ||
| **valid_base64** | No | 如果表单元素的值包含除了base64 编码字符之外的其他字符,则返回FALSE。 ||
- 第一章 Go环境配置
- 1.1 Go安装
- 1.2 GOPATH 与工作空间
- 1.3 Go 命令
- 1.4 Go开发工具
- 1.5 小结
- 第二章 Go语言基础
- 2.1 你好,Go
- 2.2 Go基础
- 2.3 流程和函数
- 2.4 struct类型
- 2.5 面向对象
- 2.6 interface
- 2.7 并发
- 2.8 总结
- 第三章 Web基础
- 3.1 Web工作方式
- 3.2 Go搭建一个Web服务器
- 3.3 Go如何使得Web工作
- 3.4 Go的http包详解
- 3.5 小结
- 第四章 表单
- 4.1 处理表单的输入
- 4.2 验证表单的输入
- 4.3 预防跨站脚本
- 4.4 防止多次递交表单
- 4.5 处理文件上传
- 4.6 小结
- 第五章 访问数据库
- 5.1 database/sql接口
- 5.2 使用MySQL数据库
- 5.3 使用SQLite数据库
- 5.4 使用PostgreSQL数据库
- 5.5 使用beedb库进行ORM开发
- 5.6 NOSQL数据库操作
- 5.7 小结
- 第六章 session和数据存储
- 6.1 session和cookie
- 6.2 Go如何使用session
- 6.3 session存储
- 6.4 预防session劫持
- 6.5 小结
- 第七章 文本处理
- 7.1 XML处理
- 7.2 JSON处理
- 7.3 正则处理
- 7.4 模板处理
- 7.5 文件操作
- 7.6 字符串处理
- 7.7 小结
- 第八章 Web服务
- 8.1 Socket编程
- 8.2 WebSocket
- 8.3 REST
- 8.4 RPC
- 8.5 小结
- 第九章 安全与加密
- 9.1 预防CSRF攻击
- 9.2 确保输入过滤
- 9.3 避免XSS攻击
- 9.4 避免SQL注入
- 9.5 存储密码
- 9.6 加密和解密数据
- 9.7 小结
- 第十章 国际化和本地化
- 10.1 设置默认地区
- 10.2 本地化资源
- 10.3 国际化站点
- 10.4 小结
- 第十一章 错误处理,调试和测试
- 11.1 错误处理
- 11.2 使用GDB调试
- 11.3 Go怎么写测试用例
- 11.4 小结
- 第十二章 部署与维护
- 12.1 应用日志
- 12.2 网站错误处理
- 12.3 应用部署
- 12.4 备份和恢复
- 12.5 小结
- 第十三章 如何设计一个Web框架
- 13.1 项目规划
- 13.2 自定义路由器设计
- 13.3 controller设计
- 13.4 日志和配置设计
- 13.5 实现博客的增删改
- 13.6 小结
- 第十四章 扩展Web框架
- 14.1 静态文件支持
- 14.2 Session支持
- 14.3 表单及验证支持
- 14.4 用户认证
- 14.5 多语言支持
- 14.6 pprof支持
- 14.7 小结
- 附录A 参考资料