当前位置: 首页 > news >正文

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框架。 **那什么是框架呢&#xff1f;**就是别人写好的代码&#xff0c;我们可以直接使用&#xff01;这个代码是专门针对某一个开发方向定制的&#xff0c;例如&#xff1a;我们要做一个网站&#xff0c;利用 beego 框架就能非常快的完成网站的开发…...

【网络原理】初始网络,了解概念

文章目录 1. 网络通信1.1 局域网LAN1.2 广域网WAN 2. 基础概念2.1 IP2.2 端口号 3. 认识协议4. 五元组5. 协议分层5.1 分层的作用5.2 OSI七层模型5.3 TCP/IP五层&#xff08;四层&#xff09;模型 6. 封装和分用 1. 网络通信 计算机与计算机之间是互相独立&#xff0c;是独立模…...

对象存储,从单机到分布式的演进

关于数据存储的相关知识,请大家关注“数据存储张”,各大平台同名。 通过《什么是云存储?从对象存储说起》我们对对象存储的历史、概念和基本使用有了一个大概的认识。而且我们以Minio为例,通过单机部署的模式实际操作了一下对象存储的GUI,感受了一下对象存储的用法。 在上…...

结构型设计模式——桥接模式

摘要 桥接模式(Bridge pattern): 使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。 一、桥接模式的意图 将抽象与实现分离开来&#xff0c;使它们可以独立变化。 二、桥接模式的类图 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&#xff0c;在编译时启用…...

C++之std::atomic解决多线程7个问题(二百四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…...

tailwindcss 如何在 uniapp 中使用

直接使用https://tailwindcss.com/docs/guides/vite这篇官方教程的写法是跑不通的&#xff0c;摸索以后整理了一下&#xff0c;最关键的是第6步 npm install -D tailwindcss postcss autoprefixernpx tailwindcss init -p在 tailwind.config.js 中写入 export default {conten…...

oracle-使用PLSQL工具自行修改用户密码

1、使用PLSQL工具&#xff0c;输入用户名和原密码登录&#xff0c;如下图 2、登录后&#xff0c;在会话下拉菜单中找到”Change password..” 3、在跳出的窗口中配置新密码&#xff0c;修改完成后单击”确认”&#xff0c;后退出PLSQL 4、重新打开PLSQL&#xff0c;使用新密码登…...

自动驾驶技术:现状与未来

自动驾驶技术&#xff1a;现状与未来 文章目录 引言自动驾驶技术的现状自动驾驶技术的挑战自动驾驶技术的未来结论结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;全新的PnC培训不…...

C++ 类构造函数 析构函数

类的构造函数 类的构造函数是类的一种特殊的成员函数&#xff0c;它会在每次创建类的新对象时执行。 构造函数的名称与类的名称是完全相同的&#xff0c;并且不会返回任何类型&#xff0c;也不会返回 void。构造函数可用于为某些成员变量设置初始值。 下面的实例有助于更好地…...

C++标准模板(STL)- 输入/输出操纵符-(std::get_time,std::put_time)

操纵符是令代码能以 operator<< 或 operator>> 控制输入/输出流的帮助函数。 不以参数调用的操纵符&#xff08;例如 std::cout << std::boolalpha; 或 std::cin >> std::hex; &#xff09;实现为接受到流的引用为其唯一参数的函数。 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&#xff09;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杂货店】类和对象&#xff08;上&#xff09; 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类对象模型7.1 类对象的存储规则7.2 例题7.3结构体内存对齐规则 八、this指针8.2 t…...

web:[极客大挑战 2019]PHP

题目 点进页面显示如下 根据页面提示&#xff0c;这个网站有备份文件&#xff0c;备份文件一般是bak文件格式&#xff0c;用dirsearch扫描 访问之后下载了一个文件 里面都是一些代码 在index.php中发现了一个类的文件&#xff0c;一个get传参&#xff0c;然后将传进的值进行反序…...

Firefox 开发团队对 Vue 3 进行优化效果显著

Mozilla 官方博客近日发表文章《Faster Vue.js Execution in Firefox》&#xff0c;介绍了 Firefox 开发团队对 Vue 3 进行的优化。 文章写道&#xff0c;在使用 Speedometer 3 对 Firefox 进行基准测试时&#xff0c;他们发现 Vue.js test 的测试结果从 Vue 2 升级到 Vue 3 后…...

【Verilog 教程】6.5 Verilog避免Latch

关键词&#xff1a;触发器&#xff0c;锁存器 Latch 的含义 锁存器&#xff08;Latch&#xff09;&#xff0c;是电平触发的存储单元&#xff0c;数据存储的动作取决于输入时钟&#xff08;或者使能&#xff09;信号的电平值。仅当锁存器处于使能状态时&#xff0c;输出才会随着…...

怒刷LeetCode的第21天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;哈希表 方法二&#xff1a;计数器数组 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;分治法 方法二&#xff1a;快速幂 迭代 方法三&#xff1a;快速幂 递归 第三题 题目来源 题目内容 …...

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)的数据预取引擎。不同…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...

​​企业大模型服务合规指南:深度解析备案与登记制度​​

伴随AI技术的爆炸式发展&#xff0c;尤其是大模型&#xff08;LLM&#xff09;在各行各业的深度应用和整合&#xff0c;企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者&#xff0c;还是积极拥抱AI转型的传统企业&#xff0c;在面向公众…...