beego 的項目基本都是通過 bee 命令來創建的,所以在創建項目之前確保你已經安裝了 bee 工具和 beego。如果你還沒有安裝,那麼請查閱 beego 的安裝 和 bee 工具的安裝。
現在一切就緒我們就可以開始創建項目了,打開終端,進入 $GOPATH/src 所在的目錄:
創建一個項目名爲20180118_loongc_beego的基於beego 的新項目,執行如下命令:
bee new 20180118_loongc_beego
依次執行如下命令:進入目錄,運行該項目,在localhost:8080裏查看,如下圖
cd 20180118_loongc_beego
bee run
安裝beego orm, 降低複雜的ORM(Object-Relational Mapping,對象關係映射)學習曲線,執行如下命令:
go get github.com/astaxie/beego
安裝postgresql數據庫驅動,執行如下命令:
go get github.com/lib/pq
在main.go文件裏添加如下代碼:
func init(){
orm.RegisterDriver(“postgres”. orm.DRPostgres)
orm.RegisterDataBase(“default”, “postgres”, “user=postgres password=nasadmin dbname=20180111_loongc_test host=127.0.0.1 port=5432 sslmode=disable”)
orm.RegisterModel(
new(models.User))
orm.RunSyncdb("default", false, true)
}
orm.RegisterDriver爲配置postgresql數據庫驅動
orm.RegisterDataBase中:
“default”是默認項
“postgres”表示使用的是postgresql數據庫
user=postgres password=nasadmin dbname=20180111_loongc_test:分別表示數據庫用戶名、用戶密碼、數據庫名
host=127.0.0.1 port=5432:分別表示數據庫主機地址、數據庫端口(5432是postgresql的默認端口)
orm.RegisterModel:表示註冊model,每添加一個model文件,都需要register,否則無法訪問。當前表示有兩個model,User和Topic
在文件夾models下新建文件User.go,文件內容如下:
package models
import (
“github.com/astaxie/beego/orm”
)
type User struct {
Id int `json: “id”`
Username string `json:”username”`
Password string `json:”password”`
Role string `json:”role”`
}
模型User構造完成,一個完整的模型還需要添加函數通用方法,這裏實現一個用戶登錄,在文件中添加用戶登錄驗證函數,如下:
func Login(username string, password string)(bool, User){
o := orm.NewOrm()
var user User
err := o.QueryTable(user).Filter(“Username”, username).Filter(“Password”, password).One(&user)
return err != orm.ErrNoRows, user
}
在views目錄底下添加login.tpl文件,tpl文件是模板寫法,本質還是遵循html文件寫法,但是支持框架本身的很多變量。文件內容如下:
<!DOCTYPE html>
<html>
<head>
<title>Login page</title>
</head>
<body >
<form id="loginform">
id:<input type="text" name="username" value="{{.Username}}"><br>
pw:<input type="password" name="password" value="{{.Password}}"><br>
<input type="button" value="submit" id="loginbtn">
</form>
<script type="text/javascript" src="/static/js/jquery-3.2.1.js"></script>
<script type="text/javascript">
$(function(){
$('#loginbtn').bind('click', function(){
$.ajax({
url: "/login",
type: "post",
asyns: true,
data: $('#loginform').serialize(),
// dataType: "json",
success: function(res){
console.log(res);
if(res){
window.location.href = "/index";
}else{
window.location.href = "/";
}
// console.log({{.flash.success}});
// {{if .flash.success}}
// window.location.href = {{.flash.success}};
// {{end}}
},
error: function(XMLHttpRequest, testStatus, errorThrown){
console.log(XMLHttpRequest.status);
console.log(XMLHttpRequest.readyState);
console.log(testStatus);
}
});
})
});
</script>
</body>
</html>
beego框架中,所有視圖view顯示,都是要定義在控制器裏的。當登錄頁面已經構建好,但是無法在瀏覽器裏馬上渲染。這也是beego的侷限性,當我需要創建一個新的tpl文件放到服務器端,然後在iframe裏通過src引用的時候,新的tpl的名字是動態的,無法動態的在控制器裏添加定義。
在當前登錄功能中,包括兩個控制器,代碼如下:
一個登錄頁面渲染控制器Loginpage,它定義了模板文件的位置,並且定義了兩個輸入框的值,在登錄頁面通過{{.Username}}的方法給用戶id輸入框設置默認值。
一個登錄驗證控制器Login,它是將用戶提交的username和password拿到之後,然後調用之前model裏定義的方法,實現驗證。驗證成功之後進入index.tpl頁面(主頁),驗證失敗仍停留在login.tpl。這裏仍存在一個beego的問題,如果使用jquery 的ajax方法,beego無法設置返回值,這裏原來的Redirect的也會失效,甚至c.TplName方法也同樣不起作用。
package controllers
import (
"github.com/astaxie/beego"
"server/20180118_loongc_beego/models"
)
type LoginController struct {
beego.Controller
}
func (c *LoginController) Loginpage() {
c.Data["Username"] = "loongc"
c.Data["Password"] = "123"
c.Data["Error"] = ""
c.TplName = "login.tpl"
}
func (c *LoginController) Login() {
flash := beego.NewFlash()
username, password := c.Input().Get("username"), c.Input().Get("password")
if flag, _ := models.Login(username, password); flag {
// c.SetSecureCookie(beego.AppConfig.String("cookie.secure"), beego.AppConfig.String("cookie.role"), user.Role, 1*1*20*60, beego.AppConfig.String("cookie.domain"), "/", false, true)
c.Redirect("/index", 302)
// c.TplName = "index.tpl"
return
} else {
flash.Error("username or password error")
c.Redirect("/error", 302)
return
}
}
登錄界面使用jquery ajax發送的請求是如何被beego框架捕獲的,因爲很明顯的是在這個案例中url給的value是 /login ,這是一個不符合一般化的ajax格式的值,這個是由beego框架自己定義的路由來控制的。在routers目錄底下有一個router.go文件,在這裏定義了前端的所有請求的最後會被分發到不同控制器,代碼如下所示:
package routers
import (
"github.com/astaxie/beego"
"server/20180118_loongc_beego/controllers"
)
func init() {
beego.Router("/", &controllers.LoginController{}, "GET:Loginpage")
beego.Router("/login", &controllers.LoginController{}, "POST:Login")
beego.Router("/index", &controllers.IndexController{}, "GET:Indexpage")
beego.Router("/error", &controllers.IndexController{}, "GET:Error")
}
這裏一共定義了四個四個不同的路由,按順序,分別是初始化web的默認打開頁面、登錄驗證控制器、初始化index.tpl(這個是登錄成功之後打開的頁面),最後一個是在本實例中設計的登錄頁面跳轉問題,後續章節繼續說明。
- 前面已經提到的,對於所有view文件的渲染,都需要事先在控制器裏定義好,對於新生成的view文件,目前來看好像無能爲力
- 其次,在於與jquery ajax的配合,beego在這種情況下好像無法返回值,當我在控制器裏添加return 一個bool值,並沒有拿到,但是通過控制器裏存在Redirect方法,console.log(res)時,可以返回Redirect的頁面代碼。基於以上,ajax無法獲得控制頁面跳轉的參數,不僅如此,beego自身的頁面跳轉也會出現失效問題。儘管官方提供了擴展方法,但是好像不是很成熟
解決登錄跳轉
在這裏還是堅持ajax做數據發送,因爲並不是所有的情況的都是通過input、testxarea、select輸入要保存的數據。
在這裏提供鑑於console.log(res)出的是要打開頁面的代碼,那麼假設驗證登錄失敗,如果打開的頁面是個空的文檔,那麼if(res) 只有在驗證正確的時候纔會恆爲true,否則就爲false,所以我在路由中定義了一個 /error 的路由,在控制器裏讓它打開一個名爲error.tpl的空文檔,當驗證錯誤的時候console.log(res)是空的,所以if(res)爲false,以此來控制登錄驗證成功與否時的跳轉。但是提示錯誤信息並沒有很好展現
beego是比較完善的框架,但是適用範圍僅限於,按照模板輸出不同數據。
後臺控制跳轉,算不得友好,尤其是前端<a>標籤都無法單獨控制頁面跳轉。
無法實現靈活的數據數據輸入,路由限制決定了數據發送方式被限定太死,不符合實際。尤其是與ajax這種很成熟的數據路由配合都很差。
輸入數據的合法性校驗,由後端完成,這種工作應該儘量由前端完成。