【小雞創(chuàng)作】beego開(kāi)發(fā)輕博客
本章目標(biāo):添加用戶登陸及注冊(cè)功能葡盗!
github: 打開(kāi)后缘屹,點(diǎn)擊右上角star按鈕
視頻教程: B站地址
初始化數(shù)據(jù)-數(shù)據(jù)庫(kù)選用sqlite3數(shù)據(jù)庫(kù)
- 安裝 gorm框架 點(diǎn)我進(jìn)入官方文檔
go get -u github.com/jinzhu/gorm
- 創(chuàng)建 models->core.go 初始化gorm
import (
"github.com/jinzhu/gorm"
//引入sqlite3的驅(qū)動(dòng)
_ "github.com/jinzhu/gorm/dialects/sqlite"
"os"
)
var (
//定義db變量似炎,變量名開(kāi)頭是小寫(xiě),只能同包下訪問(wèn)
db gorm.DB
)
func init() {
// 創(chuàng)建data目錄,0777代表文件權(quán)限
if err := os.MkdirAll("data", 0777); err != nil {
panic("failed to connect database," + err.Error())
}
//打開(kāi)數(shù)據(jù)庫(kù)棱诱,并復(fù)制給db變量瘦陈,data/data.db數(shù)據(jù)文件路徑
db, err := gorm.Open("sqlite3", "data/data.db")
//存在錯(cuò)誤,則程序退出岁疼,panic是類似于java的RuntimeException錯(cuò)誤
if err != nil {
panic("failed to connect database")
}
}
- 在main.go調(diào)用 core.go的init方法
import (
// 運(yùn)行main方法之前 調(diào)用models包下的文件的init方法阔涉。先初始化數(shù)據(jù)庫(kù)
_ "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自動(dòng)同步 用戶表結(jié)構(gòu),只需在models-core.go init方法后面添加如下代碼
func init(){
......
// 自動(dòng)同步表結(jié)構(gòu)
db.AutoMigrate(&User{})
}
- 程序啟動(dòng)的時(shí)候默認(rèn)插入admin用戶字逗,即修改models->core.go文件京郑,在init的方法結(jié)尾,判斷用戶是否存在記錄葫掉,不存在就插入admin用戶些举。
func init(){
......
// 自動(dòng)同步表結(jié)構(gòu)
db.AutoMigrate(&User{})
var count int
// Model(&User{})查詢用戶表, Count(&count) 將用戶表的數(shù)據(jù)賦值給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 框架沒(méi)有用戶登陸與注冊(cè)界面
- 新增用戶頁(yè)面:views->user.html點(diǎn)我查詢頁(yè)面代碼
- 新增用戶注冊(cè)也頁(yè)面 views->reg.html點(diǎn)我查詢頁(yè)面代碼
啟用beego的session功能
- 修改main.go俭厚,開(kāi)啟beego的session功能
func main() {
initSession()
...
}
func initSession() {
//beego的session序列號(hào)是用gob的方式户魏,因此需要將注冊(cè)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功能,每次請(qǐng)求的時(shí)候都去判斷用戶是否登陸挪挤。并將登陸的信息保存到BaseController控制器里,修改controllers->base.go 文件
//定義session中的key值
const SESSION_USER_KEY = "SESSION_USER_KEY"
...
type BaseController struct {
beego.Controller
IsLogin bool //標(biāo)識(shí) 用戶是否登陸
User models.User //登陸的用戶
}
func (ctx *BaseController) Prepare() {
// 驗(yàn)證用戶是否登陸叼丑,判斷session中是否存在用戶,存在就已經(jīng)登陸扛门,不存在就沒(méi)有登陸鸠信。
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
...
}
用戶登陸功能實(shí)現(xiàn)
- 首先咱們判斷用戶是否存在,需要到數(shù)據(jù)庫(kù)论寨,更具用戶名和密碼查詢用戶星立,如果能查到就存在,反之不存在政基。因此新增根據(jù)用戶郵箱和密碼查詢用戶的方法贞铣,修改models->user.go,添加下面代碼
func QueryUserByEmailAndPassword(email, password string) (user User, err error) {
// 這就是gorm的魅力,一句代碼即可沮明,對(duì)開(kāi)發(fā)友好。
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里面定義的窍奋,第一個(gè)參數(shù)獲取請(qǐng)求的參數(shù)的鍵值對(duì)的key荐健,請(qǐng)求后酱畅,如key對(duì)于的value是空,就返回第二個(gè)參數(shù)*/
// 判斷郵箱不能為空
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里面定義的址否,使對(duì)beego的ctx.Abort(..)的封裝餐蔬,目的:優(yōu)化錯(cuò)誤提示。
c.Abort500(syserrors.NewError("郵箱或密碼不對(duì)", err))
}
//將user保存到session
c.SetSession(SESSION_USER_KEY, user)
//JSONOk使在BaseController里面定義的佑附,使對(duì)beego的ctx.ServeJSON()的封裝樊诺,目的:優(yōu)化提示
//這里將返回 {code: 0, msg: "登陸成功", action: "/"}
c.JSONOk("登陸成功", "/")
}
- 上面咱們定義好的登陸邏輯,現(xiàn)在我們還需要定義beego的路由音同。我們使用beego的注解路由词爬,只需要修改 routers->router.go 文件添加下面一段代碼
func init() {
...
beego.Include(
&controllers.IndexController{},
&controllers.UserController{},
)
...
}
- 咱們用戶登陸的后臺(tái)業(yè)務(wù)已經(jīng)完成,現(xiàn)在開(kāi)始修改前臺(tái)頁(yè)面权均,使能夠登陸成功顿膨。前臺(tái)頁(yè)面user.html頁(yè)面已經(jīng)新增,其核心代碼:
<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="請(qǐng)輸入郵箱" 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="請(qǐng)輸入密碼"
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">注冊(cè)用戶</a>
</div>
</div>
</form>
咱們要實(shí)現(xiàn)這個(gè)form表單的提交邏輯叽赊,讓其和后臺(tái)打通恋沃,修改static->js->blog.js 。其中sysn是對(duì)jquery的ajax請(qǐng)求方法的進(jìn)一步封裝查看代碼
//
//登陸
form.on('submit(login)', function (fromdata) {
//發(fā)送ajax請(qǐng)求
sysn.post("/login", fromdata.field)
// 設(shè)置登陸成功回掉函數(shù)
.success(function (data) {
// 提示
layer.msg(data.msg);
// 后臺(tái)如果返回有action 必指,就是跳轉(zhuǎn)到新頁(yè)面芽唇。
if (data.action) {
setTimeout(function () {
window.location.href = data.action;
}, 300)
}
}).run();
return false;
});
用戶登陸已經(jīng)完成。
用戶注冊(cè)功能實(shí)現(xiàn)
1. 數(shù)據(jù)庫(kù)調(diào)整
1.1 由于郵箱和昵稱不能重復(fù)取劫,因此匆笤,我們需要新增能夠根據(jù)用戶昵稱查詢用戶和根據(jù)用戶郵箱查詢用戶的方法。用來(lái)查詢數(shù)據(jù)是否存在谱邪。代碼如下
//根據(jù)昵稱查用戶
func QueryUserByName(name string) (user User, err error) {
return user, db.db.Where("name = ?", name).Take(&user).Error
}
//根據(jù)郵箱查用戶
func QueryUserByEmail(email string) (user User, err error) {
return user, db.db.Where("email = ?", email).Take(&user).Error
}
1.2 除了判斷重復(fù)的問(wèn)題炮捧,最重要的我們還需要提供一個(gè)保存用戶的方法。代碼如下
// 保存用戶
func SaveUser(user *User) error {
return db.Create(user).Error
}
2. 控制器UserController調(diào)整
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", "確認(rèn)密碼不能為空书蚪!")
if strings.Compare(pwd1, pwd2) != 0 {
c.Abort500(errors.New("密碼與確認(rèn)密碼 必須要一致!"))
}
if u, err := models.QueryUserByName(name); err == nil && u.ID != 0 {
c.Abort500(syserrors.NewError("用戶昵稱已經(jīng)存在!", err))
}
if u, err := models.QueryUserByEmail(email); err == nil && u.ID != 0 {
c.Abort500(syserrors.NewError("用戶郵箱已經(jīng)存在迅栅!", err))
}
//開(kāi)始保存用戶
if err := models.SaveUser(&models.User{
Name: name,
Email: email,
Pwd: pwd1,
Avatar: "",
Role: 1,
}); err != nil {
c.Abort500(syserrors.NewError("用戶注冊(cè)失敗", err))
}
c.JSONOk("注冊(cè)成功", "/user")
}
3.修改前臺(tái)代碼
3.1 注冊(cè)頁(yè)面的核心代碼:
<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="請(qǐng)輸入用戶名" 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="請(qǐng)輸入郵箱" 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="請(qǐng)輸入密碼"
autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">確認(rèn)密碼</label>
<div class="layui-input-inline">
<input type="password2" name="password2" required lay-verify="required"
placeholder="請(qǐng)輸入密碼"
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">注冊(cè)</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
3.2 修改static->js->blog.js 代碼如下
//注冊(cè)
form.on('submit(reg)', function (fromdata) {
sysn.post("/reg", fromdata.field)
.success(function (data) {
// 設(shè)置登陸成功回掉函數(shù)
layer.msg(data.msg);
// 后臺(tái)如果返回有action 殊校,就是跳轉(zhuǎn)到新頁(yè)面。
if (data.action) {
setTimeout(function () {
window.location.href = data.action;
}, 300)
}
}).run();
return false;
});
用戶注冊(cè)功能完成
總結(jié)
本講读存,我們實(shí)現(xiàn)了登陸和注冊(cè)兩個(gè)功能为流。我們程序的大概流程是:頁(yè)面發(fā)送請(qǐng)求 呕屎,beego接收請(qǐng)求,匹配咱們定義好的路由敬察,調(diào)用對(duì)應(yīng)的controller方法秀睛,再由controller的方法去查數(shù)據(jù)庫(kù),做一些業(yè)務(wù)的處理莲祸,返回結(jié)果給頁(yè)面蹂安。我們主要定義好 路由規(guī)則(beego的Router)、核心業(yè)務(wù)邏輯(beego的Controller)锐帜、數(shù)據(jù)庫(kù)操作的方法田盈,即可。
下講抹估,我們就實(shí)現(xiàn)用戶的文章錄入的功能缠黍。下講再見(jiàn)??