beego---ORM相关操作
Beego框架是go语言开发的web框架。
**那什么是框架呢?**就是别人写好的代码,我们可以直接使用!这个代码是专门针对某一个开发方向定制的,例如:我们要做一个网站,利用 beego 框架就能非常快的完成网站的开发,如果没有框架,每一个细节都需要我们处理,开发速度会大大降低。
go语言的web框架:beego,gin,echo等等,那为什么我们选择beego呢?
第一,beego是中国人开发的,开发文档比较详细,beego官网网址: https://beego.me/ 。第二,现在公司里面用beego的也比较多,比如今日头条,百度云盘,腾讯,阿里等。
2.2MVC架构
Beego是MVC架构。MVC 是一种应用非常广泛的体系架构,几乎所有的编程语言都会使用到,而且所有的程序员在工作中都会遇到!用 MVC 的方式开发程序,可以让程序的结构更加合理和清晰。 我们画图说明
beego具体是如何内嵌MVC呢?我们搭起环境通过代码分析。
2.3环境搭建
这里默认大家已经搭建好了go语言的开发环境。
-
需要安装Beego源码和Bee开发工具//sudo apt-get install
$ go get -u -v github.com/astaxie/beego $ go get -u -v github.com/beego/bee
beego源码大家都了解,就是框架的源码。
Bee开发工具带有很多Bee命令。比如
bee new
创建项目,bee run
运行项目等。用bee运行项目,项目自带热更新(是现在后台程序常用的一种技术,即在服务器运行期间,可以不停服替换静态资源。替换go文件时会自动重新编译。)
安装完之后,bee可执行文件默认存放在
$GOPATH/bin
里面,所以需要把$GOPATH/bin
添加到环境变量中才可以进行下一步$ cd ~ $ vim .bashrc //在最后一行插入 export PATH="$GOPATH/bin:$PATH" //然后保存退出 $ source .bashrc
安装好之后,运行
bee new preojectName
来创建一个项目,注意:通过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,显示如下:
解决bee问题的
https://blog.csdn.net/lilian129/article/details/128416866?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169596966316800197053200%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=169596966316800197053200&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-128416866-null-null.142^v94^control&utm_term=Failed%20to%20build%20the%20application%3A%20main.go%3A5%3A2%3A%20missing%20go.sum%20entry%20for%20module%20providing%20package%20github.com%2Fbeego%2Fbeego%2Fv2%2Fserver%2Fweb%20%28imported%20by%20projectName%29%3B%20to%20add%3A%20%20%20%20%20%20%20%20%20go%20get%20projectName&spm=1018.2226.3001.4187
2.4beego的项目结构分析
quickstart
|-- conf
| `-- app.conf
|-- controllers
| `-- default.go
|-- main.go
|-- models
|-- routers
| `-- router.go
|-- static
| |-- css
| |-- img
| `-- js
|-- tests
| `-- default_test.go
|-- views`-- index.tpl
conf文件夹:放的是项目有关的配置文件
controllers:存放主要的业务代码
main.go:项目的入口文件
models:存放的是数据库有关内容
routers:存放路由文件,路由作用是根据不同的请求指定不同的控制器
static:存放静态资源,包括图片,html页面,css样式,js文件等
tests:测试文件
**views:**存放视图有关内容
后面我们重点需要操作的是MVC文件夹,routers文件夹。
2.5Beego快速体验
前面我们简单了解了 beego初始化的内容,那么就来个beego的快速体验吧!
根据上图所示的步骤,对自己创建的项目进行三步修改,然后在浏览器是否能看到修改之后的效果。
如果把你们前面做的静态网页放到views文件夹下呢?一个静态网站是不是就出现啦!有没有感受到beego开发网站的快捷!
代码分析
c.Data["Email"] = "astaxie@gmail.com"
是给视图传递数据,在视图界面里面需要用{{ }}
加上.
才能获取到,比如这行代码的意思就是,给视图传递,**Key为Email,value为astaxie@gmail.com **的数据。在视图中要通过{{.Email}}
就能获取到value值。
c.TplName = "index.tpl"
的作用是指定视图。这里面需要注意的是,默认指定的界面是tpl结尾,但是打开这个文件分析,发现还是一个html界面。所以我们也可以用html文件当视图文件。
示例
package controllersimport (beego "github.com/beego/beego/v2/server/web"
)type MainController struct {beego.Controller
}func (c *MainController) Get() {c.Data["Website"] = "beego.vip" //传递数据给视图c.Data["Email"] = "astaxie@gmail.com" //传递数据给视图c.Data["data"] = "china"//c.TplName = "index.tpl" //指定视图文件c.TplName = "test.html"
}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
hello world{{.data}}
</body>
</html>
通过我们对Beego的快速体验能够得出如下结论:
控制器(Controller)的作用
1.能够给视图传递数据
2.能够指定视图
**视图(View)的作用 **
1.view本质就是个html。所以能在浏览器显示
2.能够接收控制器传递过来的数据
2.6Beego运行流程分析
-
浏览器发出请求
-
路由拿到请求,并给相应的请求指定相应的控制器
-
找到指定的控制器之后,控制器看是否需要查询数据库
-
如果需要查询数据库就找model取数据
-
如果不需要数据库,直接找view要视图
-
控制器拿到视图页面之后,把页面返回给浏览器
根据文字流程分析代码流程
-
从项目的入口main.go开始
-
找到router.go文件的Init函数
-
找到路由指定的控制器文件default.go的Get方法
-
然后找到指定视图的语法,整个项目就串起来啦。
2.7Post案例实现
刚才我们分析了beego项目的整个运行流程,最终是如何调到Get方法的呢?beego通过内部语法给不同的http请求指定了不同的方法,因为我们是从浏览器地址栏发送的请求,属于get请求,所以调用的是Get方法。为了检验老师说的对不对,我们可以实现一个post请求,看看效果。
2.7.1前端修改
前端代码如下:
修改我们刚才创建的新的视图,为了能够发送post请求,我们在视图中添加一个能发送post请求的控件form
<form method="post" action="/index"><input type="submit">
</form>
然后设置一个能接收后台传递过来的数据的标签
<h1>hello {{.data}}</h1>
全部代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form method="post" action="/index"><input type="submit">
</form>
<h1>hello {{.data}}</h1></body>
</html>
2.7.2后台代码修改
后台代码
先设置我们Get请求要传递的数据和要显示的视图页面
func (c *MainController) Get() {c.Data["data"] = "world"c.TplName = "test.html" //渲染
}
再设置我们post请求要传递的数据和要显示的视图页面
func (c *MainController) Post() {c.Data["data"] = "xxxxxx"c.TplName = "test.html" //渲染
}
操作
先在浏览器输入网址,然后点击页面上的按钮,看一下页面的变化,有没有出现xxxxxx
几个字
2.8Beego中路由的快速体验
2.8.1路由的简单设置
路由的作用:根据不同的请求指定不同的控制器
路由函数:beego.Router("/path",&controller.MainController{})
函数参数:
先分析一下Url地址由哪几部分组成? 同一资源定位符
http://192.168.110.71:8080/index
**http://地址:端口/资源路径 **
第一个参数:资源路径,也就是/
后面的内容
第二个参数:需要指定的控制器指针
了解上面的内容之后我们来看几个简单的例子:
beego.Router("/", &controllers.MainController{})
beego.Router("/index", &controllers.IndexController{})
beego.Router("/login", &controllers.LoginController{})
2.8.2高级路由设置
一般在开发过程中,我们基本不使用beego提供的默认请求访问方法,都是自定义相应的方法。那我们来看一下如何来自定义请求方法。
自定义请求方法需要用到Router的第三个参数。这个参数是用来给不同的请求指定不同的方法。具体有如下几种情况。
-
一个请求访问一个方法(也是最常用的),请求和方法之间用
:
隔开,不同的请求用;
隔开:beego.Router("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
-
可以多个请求,访问一个方法 ,请求之间用
,
隔开,请求与方法之间用:
隔开:beego.Router("/api",&RestController{},"get,post:ApiFunc")
-
所有的请求访问同一个方法,用
*
号代表所有的请求,和方法之间用:
隔开:beego.Router("/api/list",&RestController{},"*:ListFood")
-
如果同时存在 * 和对应的 HTTP请求,那么优先执行 HTTP请求所对应的方法,例如同时注册了如下所示的路由:
beego.Router("/simple",&SimpleController{},"*:AllFunc;post:PostFunc")
那么当遇到Post请求的时候,执行PostFunc而不是AllFunc。
如果用了自定义方法之后,默认请求将不能访问。
2.9Go操作MySQL数据库(复习)
-
安装go操作MySQL的驱动
go get -u -v github.com/go-sql-driver/mysql
-
go简单操作MySQL数据库
-
导包
import "github.com/go-sql-driver/mysql"
-
连接数据库,用sql.Open()方法,open()方法的第一个参数是驱动名称,第二个参数是用户名:密码@tcp(ip:port)/数据库名称?编码方式,返回值是连接对象和错误信息,例如:
conn,err := sql.Open("mysql","root:123456@tcp(127.0.0.1:3306)/test?charset=utf8") defer conn.Close()//随手关闭数据库是个好习惯
-
执行数据库操作,这一步分为两种情况,一种是增删改,一种是查询,因为增删改不返回数据,只返回执行结果,查询要返回数据,所以这两块的操作函数不一样。
创建表
创建表的方法也是Exec(),参数是SQL语句,返回值是结果集和错误信息:
res ,err:= conn.Exec("create table user(name VARCHAR(40),pwd VARCHAR(40))") beego.Info("create table result=",res,err)
-
示例
package modelsimport ("database/sql""github.com/beego/beego/v2/core/logs"_ "github.com/go-sql-driver/mysql"
)func init() {//操作数据库代码//第一个参数是数据库驱动,第二个参数是链接数据库字符串 //root:root@tcp(127.0.0.1:3306)charset=utf8conn, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test?charset=utf8")if err != nil {logs.Info("连接错误", err)logs.Error("连接错误", err)return}//创建表// You have an error in your SQL syntax; check the manual that corresponds to your MySQL// server version for the right syntax to use near 'password VARCHAR)'//_, err1 := conn.Exec("create table user(name VARCHAR,password VARCHAR);") //写法错误,//if err1 != nil {// logs.Info("创建失败", err1)// logs.Error("创建失败", err1)// return//}conn.Exec("create table user(name VARCHAR(40),password VARCHAR(40))") //必须定义VARCHAR(40)这样定义//关闭数据库defer conn.Close()//增加删除改查
}
增删改操作
执行增删改操作语句的是Exec(),参数是SQL语句,返回值是结果集和错误信息,通过对结果集的判断,得到执行结果的信息。以插入数据为例代码如下:
res,_:=stmt.Exec("insert into user(name,pwd) values (?,?)","tony","tony")
//count,_:=res.RowsAffected()
//this.Ctx.WriteString(strconv.Itoa(int(count)))
示例
package modelsimport ("database/sql""github.com/beego/beego/v2/core/logs"_ "github.com/go-sql-driver/mysql"
)func init() {//操作数据库代码//第一个参数是数据库驱动,第二个参数是链接数据库字符串 //root:root@tcp(127.0.0.1:3306)charset=utf8conn, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test?charset=utf8")if err != nil {logs.Info("连接错误", err)logs.Error("连接错误", err)return}//关闭数据库defer conn.Close()//增加 ?占位符conn.Exec("insert into user(name,password) values (?,?)", "chengpeng", "aini")
}
查询操作
用的函数是Query(),参数是SQL语句,返回值是查询结果集和错误信息,然后循环结果集取出其中的数据。代码如下:
data ,err :=conn.Query("SELECT name from user")var userName stringif err == nil{for data.Next(){data.Scan(&userName)beego.Info(userName)}}
示例
package modelsimport ("database/sql""github.com/beego/beego/v2/core/logs"_ "github.com/go-sql-driver/mysql"
)func init() {//操作数据库代码//第一个参数是数据库驱动,第二个参数是链接数据库字符串 //root:root@tcp(127.0.0.1:3306)charset=utf8conn, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test?charset=utf8")if err != nil {logs.Info("连接错误", err)logs.Error("连接错误", err)return}//关闭数据库defer conn.Close()rows, err := conn.Query("select name from user")if err != nil {return}var name stringfor rows.Next() { //循环查询rows.Scan(&name)logs.Info(name)}
}
全部代码
//连接数据库conn,err := sql.Open("mysql","root:123456@tcp(127.0.0.1:3306)/testtest?charset=utf8")if err != nil{beego.Info("链接失败")}defer conn.Close()//建表res ,err:= conn.Exec("create table user(userName VARCHAR(40),passwd VARCHAR(40))")beego.Info("create table result=",res,err)//插入数据res,err =conn.Exec("insert user(userName,passwd) values(?,?)","itcast","heima")beego.Info(res,err)//查询数据data ,err :=conn.Query("SELECT userName from user")var userName stringif err == nil{for data.Next(){data.Scan(&userName)beego.Error(userName)}}
2.10 ORM框架
Beego中内嵌了ORM框架,用来操作数据库。那么ORM框架是什么呢?ORM框架是Object-RelationShip-Mapping的缩写,中文叫对象关系映射,他们之间的关系,我们用图来表示:
2.10.1 ORM初始化
-
首先要导包
import "github.com/beego/beego/v2/client/orm"
-
然后要定义一个结构体
type User struct{Id intName stringPassWord string }
思考:如果表名和字段名为小写会发生什么结果?
注意观察数据库表中的字段和结构体中的字段是否一样?
-
然后向数据库中注册表,这一步又分为三步:
-
连接数据库
用RegisterDataBase()函数
第一个参数为数据库别名,也可以理解为数据库的key值,项目中必须有且只能有一个别名为default
的连接,
第二个参数是数据库驱动,这里我们用的是MySQL数据库,所以以MySQL驱动为例
第三个参数是连接字符串,和传统操作数据库连接字符串一样,格式为:用户名:密码@tcp(ip:port)/数据库名称?编码方式,代码如下:orm.RegisterDataBase("default","mysql","root:123456@tcp(127.0.0.1:3306)/class1?charset=utf8")
注意:ORM只能操作表,不能操作数据库,所以我们连接的数据库要提前在MySQL终端创建好。
-
注册数据库表
用orm.RegisterModel()函数,参数是结构体对象,如果有多个表,可以用
,
隔开,多new几个对象:orm.RegisterModel(new(User))
-
生成表
用orm.RunSyncdb()函数,这个函数有三个参数,
第一个参数是数据库的别名和连接数据库的第一个参数相对应。
第二个参数是是否强制更新,一般我们写的都是false,如果写true的话,每次项目编译一次数据库就会被清空一次,fasle的话会在数据库发生重大改变(比如添加字段)的时候更新数据库。
第三个参数是用来说,生成表过程是否可见,如果我们写成课件,那么生成表的时候执行的SQL语句就会在终端看到。反之看不见。代码如下:
orm.RunSyncdb("default",false,true)
-
完整代码如下:
package modelsimport ("github.com/beego/beego/v2/client/orm"_ "github.com/go-sql-driver/mysql"
)// 定义一个结构体
type User struct {Id int //id默认为主键Name stringPassWord string//在ORM里面__是有特殊含义的//Pass_Word
}func init() {//ORM操作数据库//获取连接对象orm.RegisterDataBase("default", "mysql", "root:root@tcp(127.0.0.1:3306)/test?charset=utf8")//创建表//注册表 new是分配内存orm.RegisterModel(new(User))//生成表//第一个参数是数据库别名//第二个参数是是否强制更新 false表变化很大,就会强制更新,true每次启动项目,就会drop掉,强制更新//第三个参数是否可见执行过程orm.RunSyncdb("default", false, true)//操作表
}
因为这里我们把ORM初始化的代码放到了 models包的init()函数里面,所以如果我们想让他执行的话就需要在main.go里面加入这么一句代码:
import _ "classOne/models"
2.10.2 简单的ORM增删改查操作
在执行ORM的操作之前需要先把ORM包导入,但是GoLand会自动帮我们导包,也可以手动导包
import "github.com/beego/beego/v2/client/orm"
插入
-
先获取一个ORM对象,用orm.NewOrm()即可获得
o := orm.NewOrm()
-
定义一个要插入数据库的结构体对象
var user User
-
给定义的对象赋值
user.Name = "chengpeng" user.Passwd = "chengpeng"
这里不用给Id赋值,因为建表的时候我们没有指定主键,ORM默认会以变量名为Id,类型为int的字段当主键,至于如何指定主键,我们明天详细介绍。
-
执行插入操作,o.Insert()插入,参数是结构体对象,返回值是插入的id和错误信息。
id, err := o.Insert(&user) if err == nil {fmt.Println(id) }
示例
func (c *MainController) ShowGet() {//获取ORM的对象newOrm := orm.NewOrm()//执行某个操作函数,增删改查//赋值var user models.Useruser.Name = "chengpeng"user.PassWord = "ziyeaiaiai"//插入操作count, err := newOrm.Insert(&user)if err != nil {logs.Error("插入失败")return}//插入多少条logs.Info("chengpeng:::", count)//返回结果c.Data["data"] = "asdasda"c.TplName = "test.html"
}
路由写法
查询
-
也是要先获得一个ORM对象
o := orm.NewOrm()
-
定义一个要获取数据的结构体对象
var user User
-
给结构体对象赋值,相当于给查询条件赋值
user.Id= "chengpeng"
-
查询,用o.Read(),第一个参数是对象地址,第二个参数是指定查询字段,返回值只有错误信息。
err := o.Read(&user,"Name") if err != nil{beego.Info("查询数据错误",err)return}
如果查询字段是查询对象的主键的话,可以不用指定查询字段
示例
func (c *MainController) ShowGet() {//获取ORM的对象newOrm := orm.NewOrm()//执行某个操作函数,增删改查//查询var user models.Useruser.Id = 1err := newOrm.Read(&user, "Id")if err != nil {logs.Error("查询失败", err)return}//返回结果logs.Info("结果:", user)c.Data["data"] = "asdasda"c.TplName = "test.html"
}
更新
-
一样的套路,先获得ORM对象
o := orm.NewOrm()
-
定义一个要更新的结构体对象
var user User
-
给结构体对象赋值,相当于给查询条件赋值
user.Name = "chengpeng"
-
查询要更新的对象是否存在
err := o.Read(&user) if err != nil{beego.Info("查询数据错误",err)return }
-
如果查找到了要更新的对象,就给这个对象赋新值
user.Passwd = "chengpeng"
-
执行更新操作,用o.Update()函数,参数是结构体对象指针,返回值是更新的条目数和错误信息
count,err=o.Update(&user) if err != nil{beego.Info("更新数据错误",err)return }
示例
func (c *MainController) ShowGet() {//获取ORM的对象newOrm := orm.NewOrm()//执行某个操作函数,增删改查//更新操作var user models.Useruser.Id = 1//先查询是否存在err := newOrm.Read(&user, "Id")if err != nil {logs.Error("要更新的数据不存在", err)return}user.Name = "chengpeng2"count, err := newOrm.Update(&user)if err != nil {logs.Error("更新失败", err)return}//返回结果logs.Info("结果:", count)c.Data["data"] = "asdasda"c.TplName = "test.html"
}
删除
-
同样的,获取ORM对象,获取要删除的对象
o := orm.NewOrm() var user User
-
给删除对象赋值,删除的对象主键必须有值,如果主键没值,就查询一下。我们这里直接给主键赋值。
user.Id = 1
-
执行删除操作,用的方法是o.Delete(),参数是删除的结构体对象,返回值是删除的条目数和错误信息
num, err := o.Delete(&User{Id: 1}) if err == nil {fmt.Println(num) }
示例
func (c *MainController) ShowGet() {//获取ORM的对象newOrm := orm.NewOrm()//执行某个操作函数,增删改查//更新操作var user models.Useruser.Id = 1//如果不查询直接删除,删除对象的主键要有值count, err := newOrm.Delete(&user, "Id")if err != nil {logs.Error("删除失败", err)return}//返回结果logs.Info("结果:", count)c.Data["data"] = "asdasda"c.TplName = "test.html"
}
3.当天案例
我们今天以注册和登陆作为我们今天的大练习,把今天讲到的内容都串起来。先注册,然后登陆。
在开始具体的业务之前我们要做数据库设计,在正式开发中这一步是非常重要,也比较复杂的,但是今天我们只实现登陆和注册,就简单有个用户名和密码即可,model.go内容如下:
package modelsimport ("github.com/beego/beego/v2/client/orm"_ "github.com/go-sql-driver/mysql"
)type User struct {Id intName stringPasswd string
}func init(){//1.连接数据库orm.RegisterDataBase("default","mysql","root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")//2.注册表orm.RegisterModel(new(User))//3.生成表//1.数据库别名//2.是否强制更新//3.创建表过程是否可见orm.RunSyncdb("default",false,true)
}
3.1注册
确定注册请求路径,修改路由文件
我们这里以/register
作为注册的请求路径。所以这里我们需要修改router.go文件的内容。
在router.go文件的init()函数中加下面这行代码:
beego.Router("/register", &controllers.UserController{},"get:ShowRegister")
根据上面路由的指定,我们需要添加注册控制器
在controllers文件夹下创建一个user.go,然后在这个文件里面定义一个结构体UserController
当控制器。
type UserController struct{beego.Controller
}
注意这里面添加的
beego.Controller
,是为了继承自beego自带的控制器。
添加显示注册页面函数
添加函数的时候需要注意,这个函数必须是UserController
的函数才可以,不然在路由里面调用不到。那如何把函数设置成UserController
的成员函数呢?是在函数名前面加上括号,然后放上UserController
的指针。这里我们先指定注册的视图。代码如下:
func (c *UserController)ShowRegister(){c.TplName = "register.html"
}
注意:这里如果函数名首字母小写,路由同意找不到函数,所以函数名首字母必须大写
添加视图页面
在views文件夹下面创建一个名字为register.html
的文件。然后实现成类似界面:
我们做后台的不关注样式,明天直接拿现成的样式来用即可,我们重在实现功能。
form标签里面需要添加两个属性,一个是action,一个是method,action其实就是请求路径,这里处理的还是注册业务,所以我们还用register请求,action = "/register"
,因为是上传数据,所以我们把method设置为post,即method="post"
,代码如下:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>注册页面</title>
</head>
<body><div style="position:absolute;left:50%; top:50%;"><form action="/register" method="post">用户名:<input type="text" name="userName"><p> </p>密码:<input type="password" name="passwd"><p> </p><input type="submit" value="注册"></form>
</div>
</body>
</html>
让项目运行起来,然后我们在浏览器里面输入相应的地址就能看见我们的注册页面了。
显示完注册页面之后,接着我们来处理注册的post请求。因为action="/register",method="post"
,所以我们可以去router.go界面给post请求指定相应的方法。修改如下:
beego.Router("/register", &controllers.UserController{},"get:ShowRegister;post:HandleRegister")
指定方法名之后我们就需要去控制器中实现他。
注册业务处理
-
首先在user.go中添加这个函数:
func (this*UserController)HandleRegister(){ }
-
接着开始处理注册业务
-
首先要获取数据。这里给大家介绍一类方法,这类方法将会在我们项目一中高频率的出现,因为他的作用太强大了。
**this.GetString():**获取字符串类型值
**this.GetInt():**获取整型值
**this.GetFloat:**获取浮点型值
…
**this.GetFile():**获取上传的文件
**作用:**接收前端传递过来的数据,不管是get请求还是post请求,都能接收。
**参数: ** 是传递数据的key值,一般情况下是form表单中标签的name属性值
**返回值:**根据返回类型不同,返回值也不一样,最常用的GetString()只有一个返回值,如果没有取到值就返回空字符串,其他几个函数会返回一个错误类型。获取的值一般是标签里面的value属性值。至于比较特殊的,我们用到的时候给大家做介绍。
知道了获取数据函数,我们就可以获取前端传递过来的数据啦。
-
获取注册的用户名和密码
userName := this.GetString("userName") passwd := this.GetString("passwd")
-
对数据进行校验
一般情况下,我们做服务器开发,从前端拿过来数据都要进行一系列的校验,然后才会用数据对数据库进行操作。不做校验的服务器很容易被黑掉。这里我们只做简单的判空校验。
if userName == "" || passwd == ""{beego.Info("数据数据不完整,请重新输入!")this.TplName = "register.html"return }
思考:如何把那句错误提示传递给视图?
-
把数据插入数据库
如果数据校验没有问题,那我们就需要把数据插入到数据库中。数据库插入操作前面刚讲过,这里就不一步一步的分开介绍了,代码如下:
//获取orm对象o := orm.NewOrm()//获取要插入的数据对象var user models.User//给对象赋值user.Name = userNameuser.Passwd = passwd//把数据插入到数据库if _,err := o.Insert(&user);err != nil{beego.Info("注册失败,请更换用户名再次注册!")this.TplName = "register.html"return}
因为我们现在还没有其他界面,如果跳转成功就返回一句话
注册成功
,等我们实现了登陆界面之后再实现注册之后跳转登陆界面的操作。给浏览器返回一句化的代码如下:
this.Ctx.WriteString("注册成功!")
-
user页面
package controllersimport ("github.com/beego/beego/v2/client/orm""github.com/beego/beego/v2/core/logs"beego "github.com/beego/beego/v2/server/web""projectName/models"
)type UserController struct {//继承beego.Controller
}// 显示注册页面
func (this *UserController) ShowRegister() {this.TplName = "register.html"
}func (this *UserController) HandlePost() {//获取数据userName := this.GetString("userName")pwd := this.GetString("password")//校验数据//logs.Info(userName, pwd)if userName == "" || pwd == "" {this.Data["errmsg"] = "注册数据不完整,请重新注册!"logs.Info("注册数据不完整,请重新注册!")this.TplName = "register.html"return}//操作数据//获取ORM对象newOrm := orm.NewOrm()//获取插入对象var user models.User//给插入对象赋值user.Name = userNameuser.PassWord = pwd//插入_, err := newOrm.Insert(&user)if err != nil {logs.Error("插入失败", err)return}//返回结果//返回页面this.Ctx.WriteString("注册成功")
}
router–路由
beego.Router("/register", &controllers.UserController{}, "get:ShowRegister;post:HandlePost")
前端页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>注册页面</title>
</head>
<body><form method="post" action="/register">用户名:<input type="text" name="userName">密码:<input type="password" name="password"><input type="submit" value="注册"></form>
{{.errmsg}}
</body>
</html>
3.2登陆
登陆和注册业务流程差不多,差别也就体现在一个是对数据的查询一个是数据的插入,讲义里面就不做详细分析,直接贴代码。
路由文件修改
添加下面一行代码:
beego.Router("/login", &controllers.UserController{},"get:ShowLogin;post:HandleLogin")
后台代码修改
在控制器中添加展示登录页的函数ShowLogin
和处理登陆数据的函数HandleLogin
。完整代码如下:
// 展示登录页面
func (this *UserController) ShowLogin() {this.TplName = "login.html"
}func (this *UserController) HandleLogin() {//获取数据userName := this.GetString("userName")pwd := this.GetString("password")//校验数据if userName == "" || pwd == "" {this.Data["errmsg"] = "登录失败,密码或用户错误!"logs.Info("密码或用户错误,请重新输入!")this.TplName = "login.html"return}//操作数据//获取ORM对象newOrm := orm.NewOrm()var user models.Useruser.Name = userName//user.PassWord = pwderr := newOrm.Read(&user, "Name")if err != nil {this.Data["errmsg"] = "用户不存在!"this.TplName = "login.html"return}if user.PassWord != pwd {this.Data["errmsg"] = "密码错误!"this.TplName = "login.html"return}//返回页面this.Ctx.WriteString("登录成功")
}
添加视图文件
登陆界面和注册界面很相似,拷贝过来简单修改一下即可,代码如下:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登陆页面</title>
</head>
<body><div style="position:absolute;left:50%; top:50%;"><form action="/login" method="post">用户名:<input type="text" name="userName"><p> </p>密码:<input type="password" name="passwd"><p> </p><input type="submit" value="登陆"></form>
</div>
</body>
</html>
这样我们的登陆和注册就算完成了,但是有一个问题,我们的登陆注册还是各干各的,没有关联起来,我们前面等登陆页面实现完之后,注册成功就跳转到登陆页面。现在我们来实现一下跳转。
3.3页面之间的跳转
beego里面页面跳转的方式有两种,一种是重定向,一种是渲染,都能够在浏览器上显示新的页面
3.3.1重定向
//这里的this不是this指针
重定向用到的方法是this.Redirect()
函数,有两个参数,第一个参数是请求路径,第二个参数是http状态码。
请求路径就不说了,就是和超链接一样的路径。
我们重点介绍一下状态码:
状态码一共分为五类:
1xx : 服务端已经接收到了客户端请求,客户端应当继续发送请求 。常见的请求:100
2xx :请求已成功 (已实现)常见的请求:200
3xx :请求的资源转换路径了,请求被跳转。常见的请求:300,302
4xx :客户端请求失败。常见的请求:404
5xx :服务器端错误。常见的请求:500
状态码详解:http://tool.oschina.net/commons?type=5
重定向的工作流程是:
1:当服务端向客户端响应 redirect后,并没有提供任何view数据进行渲染,仅仅是告诉浏览器响应为 redirect,以及重定向的目标地址2:浏览器收到服务端 redirect 过来的响应,会再次发起一个 http 请求3:由于是浏览器再次发起了一个新的 http 请求,所以浏览器地址栏中的 url 会发生变化4:浏览中最终得到的页面是最后这个 重定向的url 请求后的页面5:所以redirect("/register",302) 相当于你在浏览器中手动输入 localhost/register
3.3.2渲染
渲染就是控制期把一些数据传递给视图,然后视图用这些输出组织成html界面。所以不会再给浏览器发请求,是服务器自己的行为,所以浏览器的地址栏不会改变,但是显示的页面可能会发生变化。用的函数是:this.TplName = "login.html"
3.3.3两者之间的区别
区别 | 重定向 | 渲染 |
---|---|---|
响应方式 | 告诉浏览器相应是redirect,然后返回一个新的地址给浏览器,让浏览器重新发起请求 | 直接给浏览器返回视图 |
地址栏显示 | 浏览器地址栏显示的是新的地址 | 浏览器地址栏显示的还是原来的地址 |
作用 | 不能给视图传递数据,但是能够获取到加载页面时的数据 | 能够给视图传递数据,但如果要获取加载页面时的数据,需要再次写相关代码 |
使用场景 | 页面跳转的时候 | 页面加载或者是登陆注册失败的时候 |
相关文章:
beego---ORM相关操作
Beego框架是go语言开发的web框架。 **那什么是框架呢?**就是别人写好的代码,我们可以直接使用!这个代码是专门针对某一个开发方向定制的,例如:我们要做一个网站,利用 beego 框架就能非常快的完成网站的开发…...
【网络原理】初始网络,了解概念
文章目录 1. 网络通信1.1 局域网LAN1.2 广域网WAN 2. 基础概念2.1 IP2.2 端口号 3. 认识协议4. 五元组5. 协议分层5.1 分层的作用5.2 OSI七层模型5.3 TCP/IP五层(四层)模型 6. 封装和分用 1. 网络通信 计算机与计算机之间是互相独立,是独立模…...
对象存储,从单机到分布式的演进
关于数据存储的相关知识,请大家关注“数据存储张”,各大平台同名。 通过《什么是云存储?从对象存储说起》我们对对象存储的历史、概念和基本使用有了一个大概的认识。而且我们以Minio为例,通过单机部署的模式实际操作了一下对象存储的GUI,感受了一下对象存储的用法。 在上…...
结构型设计模式——桥接模式
摘要 桥接模式(Bridge pattern): 使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。 一、桥接模式的意图 将抽象与实现分离开来,使它们可以独立变化。 二、桥接模式的类图 Abstraction: 定义抽象类的接口Implementor: 定义实现类接口 …...
keepalived的vip实现nginx节点的主备
nginx wget http://nginx.org/download/nginx-1.18.0.tar.gz tar zxvf nginx-1.18.0.tar.gzyum install -y gcc gcc-c pcre pcre-devel zlib zlib-devel openssl openssl-devel libnl3-develcd nginx-1.18.0 mkdir -p /usr/local/nginx #需要使用https,在编译时启用…...
C++之std::atomic解决多线程7个问题(二百四)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
tailwindcss 如何在 uniapp 中使用
直接使用https://tailwindcss.com/docs/guides/vite这篇官方教程的写法是跑不通的,摸索以后整理了一下,最关键的是第6步 npm install -D tailwindcss postcss autoprefixernpx tailwindcss init -p在 tailwind.config.js 中写入 export default {conten…...
oracle-使用PLSQL工具自行修改用户密码
1、使用PLSQL工具,输入用户名和原密码登录,如下图 2、登录后,在会话下拉菜单中找到”Change password..” 3、在跳出的窗口中配置新密码,修改完成后单击”确认”,后退出PLSQL 4、重新打开PLSQL,使用新密码登…...
自动驾驶技术:现状与未来
自动驾驶技术:现状与未来 文章目录 引言自动驾驶技术的现状自动驾驶技术的挑战自动驾驶技术的未来结论结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造,包含PnC、新感知等的全新专项课程上线了。理论与实践相结合,全新的PnC培训不…...
C++ 类构造函数 析构函数
类的构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。 构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。 下面的实例有助于更好地…...
C++标准模板(STL)- 输入/输出操纵符-(std::get_time,std::put_time)
操纵符是令代码能以 operator<< 或 operator>> 控制输入/输出流的帮助函数。 不以参数调用的操纵符(例如 std::cout << std::boolalpha; 或 std::cin >> std::hex; )实现为接受到流的引用为其唯一参数的函数。 basic_ostream::…...
蓝桥等考Python组别九级004
第一部分:选择题 1、Python L9 (15分) 运行下面程序,可以输出几行“*”?( ) for i in range(3): for j in range(4): print(*, end = ) print() 2345正确答案:B 2、Python L9...
gitee 远程仓库操作基础(二)
(1)clone远端仓库,本地建立分支推送 (基于远程仓库版本库 本地建立分支开发新功能) git clone gitgitee.com:xxxxx/alsa_test.git git remote add origin gitgitee.com:xxxxx/alsa_test.git进入clone过后路径代码,查看本地分支,发现该项目远程仓库有很多分支 基于…...
Scala第四章节
Scala第四章节 scala总目录 章节目标 掌握分支结构的格式和用法掌握for循环和while循环的格式和用法掌握控制跳转语句的用法掌握循环案例理解do.while循环的格式和用法 1. 流程控制结构 1.1 概述 在实际开发中, 我们要编写成千上万行代码, 代码的顺序不同, 执行结果肯定也…...
【C++入门指南】类和对象(上)
【C杂货店】类和对象(上) 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类对象模型7.1 类对象的存储规则7.2 例题7.3结构体内存对齐规则 八、this指针8.2 t…...
web:[极客大挑战 2019]PHP
题目 点进页面显示如下 根据页面提示,这个网站有备份文件,备份文件一般是bak文件格式,用dirsearch扫描 访问之后下载了一个文件 里面都是一些代码 在index.php中发现了一个类的文件,一个get传参,然后将传进的值进行反序…...
Firefox 开发团队对 Vue 3 进行优化效果显著
Mozilla 官方博客近日发表文章《Faster Vue.js Execution in Firefox》,介绍了 Firefox 开发团队对 Vue 3 进行的优化。 文章写道,在使用 Speedometer 3 对 Firefox 进行基准测试时,他们发现 Vue.js test 的测试结果从 Vue 2 升级到 Vue 3 后…...
【Verilog 教程】6.5 Verilog避免Latch
关键词:触发器,锁存器 Latch 的含义 锁存器(Latch),是电平触发的存储单元,数据存储的动作取决于输入时钟(或者使能)信号的电平值。仅当锁存器处于使能状态时,输出才会随着…...
怒刷LeetCode的第21天(Java版)
目录 第一题 题目来源 题目内容 解决方法 方法一:哈希表 方法二:计数器数组 第二题 题目来源 题目内容 解决方法 方法一:分治法 方法二:快速幂 迭代 方法三:快速幂 递归 第三题 题目来源 题目内容 …...
Armv9 Cortex-A720的L2 memory system 和 L2 Cache
9 L2 memory system Cortex-A720核心的L2内存系统通过CPU bridge连接core与DynamIQ Shared Unit-120,其中包括私有的L2缓存。 L2缓存是统一的,每个Cortex-A720核心在一个集群中都有私有的L2缓存。 L2内存系统包括使用虚拟地址(VA)和程序计数器(PC)的数据预取引擎。不同…...
蓝桥等考Python组别九级003
第一部分:选择题 1、Python L9 (15分) 运行下面程序,可以输出几行“*”?( ) for i in range(3): for j in range(4): print(*, end = ) print() 6374正确答案:B 2、Python L9...
Python异步框架大战:FastAPI、Sanic、Tornado VS Go 的 Gin
一、前言 异步编程在构建高性能 Web 应用中起着关键作用,而 FastAPI、Sanic、Tornado 都声称具有卓越的性能。本文将通过性能压测对这些框架与Go的Gin框架进行全面对比,揭示它们之间的差异。 原文:Python异步框架大战:FastAPI、Sa…...
Docker笔记1
一、Docker介绍 Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。 容器是完全使用沙箱机制&a…...
TensorFlow-Federated简介与安装
1、简介 TensorFlow Federated(TFF)是一个用于机器学习和其他分布式数据计算的开源框架。TFF 的开发旨在促进联邦学习 (FL)的开放研究和实验。联邦学习是一种机器学习方法,其中一个共享的全局模型在许多参与的客户之间…...
【强化学习】基础概念
1. Agent (智能体) 智能体是进行决策和学习的实体,它能感知环境的状态,并基于策略采取动作以影响环境。智能体的目标是通过与环境的交互获得最大化的累积奖励。 2. Environment (环境) 环境是智能体所处的外部系统,它与智能体交互。环境的…...
云原生Kubernetes:K8S集群各组件服务重启
目录 一、理论 1.各组件服务重启命令 一、理论 1.各组件服务重启命令 (1)Master节点Node节点共同服务 systemctl restart etcd systemctl daemon-reload systemctl enable flanneld systemctl restart flanneld (2)Master节…...
闲话Python编程-循环
1. for循环 Python的for语句有点特别,只能对序列和字符串进行处理,序列自然包括list、tuple和range对象。 #!/usr/bin/env python3 # -*- coding: utf-8 -*- # 练习for语句def loop_for():names [Tom, Jack, Black]for name in names:print(name)s ab…...
建筑能源管理(3)——建筑能源监管
为了全面落实科学发展观,提高建筑能源管理水平,进一步降低能源和水资源消耗、合理利用资源,以政府办公建筑和大型公共建筑的运行节能管理为突破口,建立了既有政府办公建筑和大型公共建筑运行节能监管体系,旨在提高政府…...
中国逐年干燥度指数数据集
简介: 中国逐年干燥度指数,空间分辨率为1km,时间为1901-2022,为比值,没有单位。该数据集是基于中国1km逐月潜在蒸散发(PET)和降水量(PRE)采用比值法计算式得到ÿ…...
Azure Arc 概要:功能、管理和应用场景详解,AZ900 考点示例
文章目录 本文大纲一、什么是 Azure Arc二、使用 Azure Arc 可以做什么操作三、使用 Azure Arc 可以管理什么资源3.1 如何使用Azure Arc与服务器? 四、Azure Arc 支持的主要场景五、在 AZ900 中的考点示例5.1 示例题 15.2 示例题 2 本文大纲 本文思维导图概述的主要内容&…...
网站公司怎么做运营/缅甸最新新闻
2019独角兽企业重金招聘Python工程师标准>>> db2还是用dbvis 执行存储过程比较适合 很早就想学存储过程了,之前面试时都是问会不会存储过程,然而我只能摇摇头,看了大量博客,刚好这次可以用存储过程 ,会更方…...
西安做北郊做网站/大数据分析
BZOJ3919&&DTOJ2308 Portals题目题目描述英文题目中文翻译输入格式输出格式样例样例输入样例输出数据范围与提示样例解释数据范围题解题目 题目描述 英文题目 There is a cake placed in a labyrinth and you desperately want to eat it. You have a map of the la…...
凡科做网站关键词/百度快照官网
xargs与find经常结合来进行文件操作,平时删日志的时候只是习惯的去删除,比如 # find . -type f -name "*.log" | xargs rm -rf *就将以log结尾的文件删除了,如果我想去移动或者复制就需要使用参数来代替了。 xargs -i 参数或者-I参…...
深圳高端电商网站建设者/网页模板建站系统
第十九章 故障及问题管理670、故障是系统运行中出现的系统本身问题或任何非标准操作,已经引起或可能引起服务中断和服务质量下降的事件。671、故障处理彿发现故障时为尽快恢复系统IT服务而采取的技术上或管理上的办法。672、故障的特征:即影响度(故障影响…...
沈阳建站网页模板/搜狗网站排名软件
以下内容是本人近期开始学习html的一些笔记:有一些low,但是可以记录我学习的路程: head头标签 body内容(body)aptanaeasyExpler注释标签<!-- -->标题注释:<hx>:x的范围1--6 1最大…...
福田欧曼价格/网站推广优化招聘
Topshelf是一个开源的跨平台的宿主服务框架,只需要几行代码就可以构建一个很方便使用的windows服务。 首先安装nuget包 Topshelf。 创建一个.net core控制台程序 1 static void Main(string[] args)2 {3 #region 容器注入4 var services …...