初始化数据-数据库选用sqlite3数据库
安装 gorm框架 点我进入官方文档
go get -u github.com/jinzhu/gorm
创建 models->core.go 初始化gorm
import ( "github.com/jinzhu/gorm" //引入sqlite3的驱动 _ "github.com/jinzhu/gorm/dialects/sqlite" "os") var ( //定义db变量,变量名开头是小写,只能同包下访问 db gorm.DB )func init() { // 创建data目录,0777代表文件权限 if err := os.MkdirAll("data", 0777); err != nil { panic("failed to connect database," + err.Error()) } //打开数据库,并复制给db变量,data/data.db数据文件路径 db, err := gorm.Open("sqlite3", "data/data.db") //存在错误,则程序退出,panic是类似于java的RuntimeException错误 if err != nil { panic("failed to connect database") } }
在main.go调用 core.go的init方法
import ( // 运行main方法之前 调用models包下的文件的init方法。先初始化数据库 _ "github.com/jicg/liteblog/models" ... )func main(){ ... }
定义用户表
用户表有的字段:邮件、用户名、密码、头像,角色(管理员\非管理员)
新增models->user.go 文件,定义用户表字段。
type User struct { gorm.Model Name string `gorm:"unique_index"` Email string `gorm:"unique_index"` Avatar string Pwd string Role int `gorm:"default:1"` // 0 管理员 1正常用户}
让gorm自动同步 用户表结构,只需在models-core.go init方法后面添加如下代码
func init(){ ...... // 自动同步表结构 db.AutoMigrate(&User{}) }
程序启动的时候默认插入admin用户,即修改models->core.go文件,在init的方法结尾,判断用户是否存在记录,不存在就插入admin用户。
func init(){ ...... // 自动同步表结构 db.AutoMigrate(&User{}) var count int // Model(&User{})查询用户表, Count(&count) 将用户表的数据赋值给count字段。 if err := db.Model(&User{}).Count(&count).Error; err == nil && count == 0 { //新增 db.Create(&User{Name: "admin", //邮箱 Email: "admin@qq.com", //密码 Pwd: "123123", //头像地址 Avatar: "/static/images/info-img.png", //角色 管理员 Role: 0, }) } }
xianyan 框架没有用户登陆与注册界面
启用beego的session功能
修改main.go,开启beego的session功能
func main() { initSession() ... }func initSession() { //beego的session序列号是用gob的方式,因此需要将注册models.User gob.Register(models.User{}) //https://beego.me/docs/mvc/controller/session.md beego.BConfig.WebConfig.Session.SessionOn = true beego.BConfig.WebConfig.Session.SessionName = "liteblog-key" beego.BConfig.WebConfig.Session.SessionProvider = "file" beego.BConfig.WebConfig.Session.SessionProviderConfig = "data/session"}
使用session功能,每次请求的时候都去判断用户是否登陆。并将登陆的信息保存到BaseController控制器里,修改controllers->base.go 文件
//定义session中的key值const SESSION_USER_KEY = "SESSION_USER_KEY"... type BaseController struct { beego.Controller IsLogin bool //标识 用户是否登陆 User models.User //登陆的用户} func (ctx *BaseController) Prepare() { // 验证用户是否登陆,判断session中是否存在用户,存在就已经登陆,不存在就没有登陆。 ctx.IsLogin = false tu := ctx.GetSession(SESSION_USER_KEY) if tu != nil { if u, ok := tu.(models.User); ok { ctx.User = u ctx.Data["User"] = u ctx.IsLogin = true } } ctx.Data["IsLogin"] = ctx.IsLogin ... }
用户登陆功能实现
首先咱们判断用户是否存在,需要到数据库,更具用户名和密码查询用户,如果能查到就存在,反之不存在。因此新增根据用户邮箱和密码查询用户的方法,修改models->user.go,添加下面代码
func QueryUserByEmailAndPassword(email, password string) (user User, err error) { // 这就是gorm的魅力,一句代码即可,对开发友好。 return user, db.db.Model(&User{}).Where("email = ? and pwd = ?", email, password).Take(&user).Error }
新增 cotrollers->user.go 用户登陆控制器UserController 代码如下
type UserController struct { BaseController }// @router /login [post]func (c *UserController) Login() /*c.GetMustString(agr0,arg1 string ) 是在BaseController里面定义的,第一个参数获取请求的参数的键值对的key,请求后,如key对于的value是空,就返回第二个参数*/ // 判断邮箱不能为空 email := c.GetMustString("email", "邮箱不能为空!") // 判断密码不能为空! pwd := c.GetMustString("password", "密码不能为空!") var ( user *models.User err error ) if user, err = models.QueryUserByEmailAndPassword(email, pwd); err != nil { // About500使在BaseController里面定义的,使对beego的ctx.Abort(..)的封装,目的:优化错误提示。 c.Abort500(syserrors.NewError("邮箱或密码不对", err)) } //将user保存到session c.SetSession(SESSION_USER_KEY, user) //JSONOk使在BaseController里面定义的,使对beego的ctx.ServeJSON()的封装,目的:优化提示 //这里将返回 {code: 0, msg: "登陆成功", action: "/"} c.JSONOk("登陆成功", "/") }
上面咱们定义好的登陆逻辑,现在我们还需要定义beego的路由。我们使用beego的注解路由,只需要修改 routers->router.go 文件添加下面一段代码
func init() { ... beego.Include( &controllers.IndexController{}, &controllers.UserController{}, ) ... }
咱们用户登陆的后台业务已经完成,现在开始修改前台页面,使能够登陆成功。前台页面user.html页面已经新增,其核心代码:
<form class="layui-form" action=""> <div class="layui-form-item"> <label class="layui-form-label">邮箱</label> <div class="layui-input-inline"> <input type="text" name="email" required lay-verify="required" placeholder="请输入邮箱" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">密码</label> <div class="layui-input-inline"> <input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <button class="layui-btn" lay-submit lay-filter="login">登陆</button> <a href="/reg" class="layui-btn layui-btn-primary">注册用户</a> </div> </div></form>
咱们要实现这个form表单的提交逻辑,让其和后台打通,修改static->js->blog.js 。其中sysn是对jquery的ajax请求方法的进一步封装查看代码
// //登陆 form.on('submit(login)', function (fromdata) { //发送ajax请求 sysn.post("/login", fromdata.field) // 设置登陆成功回掉函数 .success(function (data) { // 提示 layer.msg(data.msg); // 后台如果返回有action ,就是跳转到新页面。 if (data.action) { setTimeout(function () { window.location.href = data.action; }, 300) } }).run(); return false; });
用户登陆已经完成。
用户注册功能实现
1. 数据库调整
1.1 由于邮箱和昵称不能重复,因此,我们需要新增能够根据用户昵称查询用户和根据用户邮箱查询用户的方法。用来查询数据是否存在。代码如下
//根据昵称查用户func QueryUserByName(name string) (user User, err error) { return user, db.db.Where("name = ?", name).Take(&user).Error }//根据邮箱查用户func QueryUserByEmail(email string) (user User, err error) { return user, db.db.Where("email = ?", email).Take(&user).Error }
1.2 除了判断重复的问题,最重要的我们还需要提供一个保存用户的方法。代码如下
// 保存用户func SaveUser(user *User) error { return db.Create(user).Error }
2. 控制器UserController调整
2.1 修改controllers->user.go 添加reg方法,代码如下
// @router /reg [post]func (c *UserController) Reg() { name := c.GetMustString("name", "昵称不能为空!") email := c.GetMustString("email", "邮箱不能为空!") pwd1 := c.GetMustString("password", "密码不能为空!") pwd2 := c.GetMustString("password2", "确认密码不能为空!") if strings.Compare(pwd1, pwd2) != 0 { c.Abort500(errors.New("密码与确认密码 必须要一致!")) } if u, err := models.QueryUserByName(name); err == nil && u.ID != 0 { c.Abort500(syserrors.NewError("用户昵称已经存在!", err)) } if u, err := models.QueryUserByEmail(email); err == nil && u.ID != 0 { c.Abort500(syserrors.NewError("用户邮箱已经存在!", err)) } //开始保存用户 if err := models.SaveUser(&models.User{ Name: name, Email: email, Pwd: pwd1, Avatar: "", Role: 1, }); err != nil { c.Abort500(syserrors.NewError("用户注册失败", err)) } c.JSONOk("注册成功", "/user") }
3.修改前台代码
3.1 注册页面的核心代码:
<form class="layui-form" action=""> <div class="layui-form-item"> <label class="layui-form-label">昵称</label> <div class="layui-input-inline"> <input type="text" name="name" required lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">邮箱</label> <div class="layui-input-inline"> <input type="text" name="email" required lay-verify="required" placeholder="请输入邮箱" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">密码</label> <div class="layui-input-inline"> <input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">确认密码</label> <div class="layui-input-inline"> <input type="password2" name="password2" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <button class="layui-btn" lay-submit lay-filter="reg">注册</button> <button type="reset" class="layui-btn layui-btn-primary">重置</button> </div> </div></form>
3.2 修改static->js->blog.js 代码如下
//注册 form.on('submit(reg)', function (fromdata) { sysn.post("/reg", fromdata.field) .success(function (data) { // 设置登陆成功回掉函数 layer.msg(data.msg); // 后台如果返回有action ,就是跳转到新页面。 if (data.action) { setTimeout(function () { window.location.href = data.action; }, 300) } }).run(); return false; });
用户注册功能完成
作者:qq归位
链接:https://www.jianshu.com/p/528b7c9744a6