Beego框架学习
1.1软件框架
一个公司是由公司中的各部部门来组成的,每一个部门拥有特定的职能,部门与部门之间通过相互的配合来完成让公司运转起来。
一个软件框架是由其中各个软件模块组成的,每一个模块都有特定的功能,模块与模块之间通过相互配合来完成软件的开发。
软件框架是针对某一类软件设计问题而产生的。
作用:避免重复造轮子(写重复代码)
1.2beego
beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API、Web 及后端服务等各种应用,是一个 MVC 的框架,主要设计灵感来源于 tornado、sinatra 和 flask 这三个框架,但是结合了 Go 本身的一些特性(interface、struct 嵌入等)而设计的一个框架。
Beego.me
1.3MVC
M: Model,模型,数据库操作,增删改查
V: View,视图, 接收C传输的数据,组织html界面
C: Controller,控制器, 接收数据,数据处理,传输数据给M和V并接收应答,返回应答给浏览器
通过浏览器注册用户信息。
施乐公司
MVC的产生理念: 分工。让专门的人去做专门的事。
1.4环境安装
需要安装或者升级 Beego 和 Bee 的开发工具:
go get -u github.com/astaxie/beego go get -u github.com/beego/bee
安装完之后,bee 可执行文件默认存放在 $GOPATH/bin 里面,所以需要把 $GOPATH/bin 添加到您的环境变量中,才可以进行下一步
echo 'export PATH="$GOPATH/bin:$PATH"' >> ~/.bashrc source .bashrc
安装好之后,运营bee new quickstart来创建一个项目,注意:通过bee创建的项目代码都是在$GOPATH/src目录下面。
生成的项目目录结构如下:
quickstart
|-- conf | -- app.conf |-- controllers | -- default.go |-- main.go |-- models |-- routers | -- router.go |-- static | |-- css | |-- img | -- js |-- tests | -- default_test.go -- views -- index.tpl
进入项目目录执行bee run命令,在浏览器输入网址:127.0.0.1:8080,显示如下:
1.5 beego的项目结构分析
├── conf │ └── app.conf ├── controllers │ ├── admin │ └── default.go ├── main.go ├── models │ └── models.go ├── static │ ├── css │ ├── ico │ ├── img │ └── js └── views ├── admin └── index.tpl
从上面的目录结构我们可以看出来 M(models 目录)、V(views 目录)和 C(controllers 目录)的结构, main.go 是入口文件。
1.6项目路由设置
打开我们项目的入口main.go
package main import ( _ "quickstart/routers" "github.com/astaxie/beego" ) func main() { beego.Run() }
我们知道main函数是整个项目的入口并且go的执行过程如下图所示:
这时候我们就发现了main里面导入了"quickstart/routers",并且执行了这个包里面的init函数,routers包的内容如下:
package routers import ( "quickstart/controllers" "github.com/astaxie/beego" ) func init() { beego.Router("/", &controllers.MainController{}) }
路由包里面我们看到执行了路由注册 beego.Router, 这个函数的功能是映射 URL 到 controller,第一个参数是 URL (用户请求的地址),这里我们注册的是 /,也就是我们访问的不带任何参数的 URL,第二个参数是对应的 Controller,也就是我们即将把请求分发到那个控制器来执行相应的逻辑,我们可以执行类似的方式注册如下路由:
beego.Router("/user", &controllers.UserController{})
这样用户就可以通过访问 /user 去执行 UserController 的逻辑。这就是我们所谓的路由(要在controllers包里面有名字为UserController才能调用)
1.7ORM
beego中内嵌了ORM框架,ORM框架可以将结构体和数据表进行对应起来,只需要通过结构体和对象就可以对数据表进行操作。
设计类:模型类。
ORM另外一个作用:根据设计的类生成数据库中的表。
安装ORM
go get github.com/astaxie/beego/orm go get -u github.com/go-sql-driver/mysql
// 设置数据库基本信息
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(127.0.0.1:3306)/test1?charset=utf8")
// 映射model数据
orm.RegisterModel(new(Book))
// 生成表
orm.RunSyncdb("default", false, true)
1.7.1 ORM对数据进行操作
插入
o := orm.NewOrm() var user User user.Name = "slene" user.Pwd= true id, err := o.Insert(&user) if err == nil { fmt.Println(id) }
查询
o := orm.NewOrm() user := User{Id: 1} err := o.Read(&user) 也可以指定字段查询 user := User{Name: "slene"} err = o.Read(&user, "Name") ...
更新
o := orm.NewOrm() user := User{Id: 1} if o.Read(&user) == nil { user.Name = "MyName" if num, err := o.Update(&user); err == nil { fmt.Println(num) } }
也可以指定更新的字段
// 只更新 Name o.Update(&user, "Name") // 指定多个字段 // o.Update(&user, "Field1", "Field2", ...) ...
删除
o := orm.NewOrm() if num, err := o.Delete(&User{Id: 1}); err == nil { fmt.Println(num) }
c.Data["errmsg"] = "sda" c.TplName = "login.html" 指定视图文件,同时可以给这个视图传递一些数据 能传递数据 c.Redirect("/login",302) 跳转。不能传递数据。速度快 Redirect("/login",302) 第一个参数是URL地址 第二个参数是HTTP的状态码 1xx 请求已经被接收,需要继续发送请求 100 2xx 请求成功 200 3xx 请求资源被转移,请求被转接 302 4xx 请求失败 404 5xx 服务器错误 500
1.8案例
注册
先实现注册视图
注册发送POST请求
Beego处理传过来的数据
对数据进行判断
如果成功返回登陆界面
登陆
登陆成功返回字符串
登陆失败返回注册界面
新闻发布系统
1模型创建
1.1 表属性设置
设置主键 `pk` 设置自增`auto` 当 Field 类型为 int, int32, int64, uint, uint32, uint64 时,可以设置字段为自增健,当模型定义里没有主键时,符合上述类型且名称为 Id 的 Field 将被视为自增健. 设置默认值 `default(11)` 设置长度`orm:size(100)` 设置允许为空`null`,数据库默认是非空,设置null之后就可以变为`ALLOW NULL` 设置唯一`orm:”unique”` 设置浮点数精度orm:"digits(12);decimals(4)"` 总共12位,四位是小数位 设置时间:`orm:"auto_now_add;type(datetime)"` `orm:"auto_now;type(date)"`
auto_now 每次 model 保存时都会对时间自动更新
auto_now_add 第一次保存时才设置时间
设置时间的格式:type
2 新闻信息插入
2.1请求数据处理
GetString(key string) string GetStrings(key string) []string GetInt(key string) (int64, error) GetBool(key string) (bool, error) GetFloat(key string) (float64, error)
2.2 文件上传
在beego中能够很容易的处理文件上传,但是需要特别注意在上传文件时form里面一定要添加enctype="multipart/form-data",不然浏览器不会上传你的文件
文件上传前端代码如下:
<form enctype="multipart/form-data" method="post"> <input type="file" name="uploadname" /> <input type="submit"> form>
后台代码如下:
func (c *FormController) Post() { f, h, err := c.GetFile("uploadname") defer f.Close() if err != nil { fmt.Println("getfile err ", err) } else { c.SaveToFile("uploadname", "/www/"+h.Filename) } }
注意后台保存文件名不能重复
3 新闻信息展示
3.1路由数据处理
固定路由
beego.Router("/", &controllers.MainController{})
正则路由
beego.Router("/api/:id([0-9]+)", &controllers.RController{})
自定义正则匹配数字 //匹配 /api/123
controller获取,this.Ctx.Input.Param(":id") :id = 123
beego.Router("/user/:username([\w]+)", &controllers.RController{})
正则字符串匹配 //匹配 /user/itcast
Controller获取,this.Ctx.Input.Param(":username") :username = itcast beego.Router("/download/ceshi/*", &controllers.RController{})
全匹配方式 //匹配 /download/ceshi/file/api.json
Controller获取,this.Ctx.Input.Param(":splat") :splat= file/api.json(注意,这里的splat是系统规定的关键字,写错取不到数据) beego.Router("/download/ceshi/*.*", &controllers.RController{})
文件名和文件地址匹配/download/ceshi/api.json
Controller获取 this.Ctx.Input.Param(":path") this.Ctx.Input.Param(":ext") :path = api :ext=json
注解路由
// @router /staticblock/:key [get] func (this *CMSController) StaticBlock() { … }
自定义方法
可以多个请求,访问一个方法
beego.Router("/api",&RestController{},"get,post:ApiFunc")
不同的 method 对应不同的函数,通过 ; 进行分割
beego.Router("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
所有的method访问同一个方法:
beego.Router("/api/list",&RestController{},"*:ListFood")
如果同时存在 * 和对应的 HTTP Method,那么优先执行 HTTP Method 的方法,例如同时注册了如下所示的路由
beego.Router("/simple",&SimpleController{},"*:AllFunc;post:PostFunc")
那么执行 POST 请求的时候,执行 PostFunc 而不执行 AllFunc。
注意:在注册了自定义方法之后,就不会再默认的访问GET或者POST方法
3.2查询方法
ORM 以 QuerySeter 来组织查询,每个返回 QuerySeter 的方法都会获得一个新的 QuerySeter 对象。
All方法
返回对应的结果集对象
var users []*User num, err := o.QueryTable("user").Filter("name", "slene").All(&users) fmt.Printf("Returned Rows Num: %s, %s", num, err)
One
尝试返回单条记录
var user User err := o.QueryTable("user").Filter("name", "slene").One(&user) if err == orm.ErrMultiRows { // 多条的时候报错 fmt.Printf("Returned Multi Rows Not One") } if err == orm.ErrNoRows { // 没有找到记录 fmt.Printf("Not row found") }
OrderBy
根据某一属性进行排序
3.3 视图页面数据获取与处理
Range
4 编辑新闻信息
1) 先获取详细信息 2) 修改详细信息
5 查看详细
1)所有信息的显示
6 删除信息
1) 提示是否删除(前端处理) 2) 删除信息
7 分页展示
分页的好处 1)数据都要读到缓存,加载缓慢,提升网页访问速度 2)减少页面条目数
7.1模板函数
7.2 Limit函数
7.3 Count函数
7.4 URL传参
1 分页展示
分页的好处
1)数据都要读到缓存,加载缓慢,提升网页访问速度
2)减少页面条目数
1.1模板函数
1.2 Limit函数
获取部分数据
1.3 Count函数
获取数据条目数
表关系设置
一对一
rel(one)
reverse(one)
一对多
rel(fk) //forign key reverse(many)
多对多
rel(m2m)
reverse(many)
on_delete()
设置对应的 rel 关系删除时,如何处理关系字段。
cascade 级联删除(默认值) set_null 设置为 NULL,需要设置 null = true set_default 设置为默认值,需要设置 default 值 do_nothing 什么也不做,忽略
Filter
exact / iexact 等于 contains / icontains 包含 [gt / gte](#gt / gte) 大于 / 大于等于 [lt / lte](#lt / lte) 小于 / 小于等于 startswith / istartswith 以...起始 endswith / iendswith 以...结束 in isnull
RelatedSel()
相当于inner join 一对多关系的时候必须加这个方法才能进行多表查询
Session
Cookie
小结
Model
表的设计
表的属性
表之间的关系
Insert
表的操作
把对应的字段赋值,插入
Delete
查询到数据,删除
Update
获取到相应数据,删除
Read
Queryseter方法
All One Count Limit OrderBy Filter RelatedSel LoadRelated
View
数据的获取
{{.data}} 逻辑控制 {{if }} {{else}} {{end}} {{range}} {{end}} {{range $index,$value := .data}}
视图函数
{{.data | func}}
addFuncMap()
Controller
路由相关
正则路由
URL传值
请求数据处理
This.GetInt
This.GetString
…
静态文件上传
Session
cache