使用 beego 搭建 web 应用之二
--zxp, Garfielt, 似年, AndyLam, · · 13207 次点击 · · 开始浏览Developing a web application with Beego - Part 2
欢迎回到本系列的第二部分,在这我们将用Go的Beego这个web开发框架来加速开发。如果你错过了第一部分,我建议你去读一下,因为它是这一系列的基础。
在第一部分中,我们有了一个好的开始,通过安装Beego及命令行的Bee了解并实际使用了Beego,创建一个基本的项目,添加一个控制行为,创建了一个基本的视图模板,添加一个自定义路由并以学习如何使用请求参数为结尾。
在第二部分中,我们将进入更有趣的部分,构建一个结合数据库的Web应用,使用的是Sqlite3,还要研究一下模型、表单以及验证。我希望你已经准备就绪了,下面让我们一块愉快的走到最后。
Garfielt
翻译于 3 个月 前
0人顶
翻译的不错哦!
两步视图
你会注意到manage控制器里的几个函数,代码如下:
manage.Layout = "basic-layout.tpl" manage.LayoutSections = make(map[string]string) manage.LayoutSections["Header"] = "header.tpl" manage.LayoutSections["Footer"] = "footer.tpl"
这些代码做的是建立了一个两步视图布局。你可能还不熟悉这个术语,它是指你在外部一直显示布局的地方,如侧边栏,导航,header、footer以及那些基于被执行动作的可变内容。
2 Step View Layout
我用上图来说明我的意思。绿色区域是在外部,封装视图和红色部分是基于执行动作内容将要改变的。
通过参考Layout和LayoutSections,我们能够指定外部布局的视图模板,basic-layout.tpl,以及其他的子模板,在我们的例子中为一个header和footer,分别为header.tpl和footer.tpl。
这样做的话,我们行为模板生成的内容将被插入到封装视图模板中,如通过指定{{.LayoutContent}},而header和footer分别为{{.Header}}和{{.Footer}}。
Garfielt
翻译于 3 个月 前
0人顶
翻译的不错哦!
模型
为添加数据库支持,我们需要做的几件事。首先,我们需要建立一些模型。模型基本上只是一些拥有额外信息的结构。下面是一个模型文件,在models/models.go中,我们将在应用的剩余部分中一直使用它。
package models
type Article struct {
Id int `form:"-"`
Name string `form:"name,text,name:" valid:"MinSize(5);MaxSize(20)"`
Client string `form:"client,text,client:"`
Url string `form:"url,text,url:"`
}
func (a *Article) TableName() string {
return "articles"
}
你可以看到里面有一个模型,Article,一个简单的网站文章模型,其包含四个属性: Id, Name, Client 和 Url。你需要注意的是每个属性都有额外的数据,上面提到的form 和valid。
这是将模型用来同时处理生成和验证的一个非常简单的方法。让我们通过实际使用这四个属性解释每个的作用。
Id int `form:"-"`
在我们的数据库中,ID是一个自递增字段。当添加新记录时这个值会自动生成,当删除,更新或查找记录时需要提供这个值。所以对于form:"-",我们要说的是Id不是必需的。
Name string `form:"name,text,name:" valid:"MinSize(5);MaxSize(20)"`
Garfielt
翻译于 3 个月 前
0人顶
翻译的不错哦!
我们这里有一个稍微复杂一些的例子,让我们分解开来,以"name,text,name:"开头。它的意思是当表单被解析的时候,我们将会看到:
来自表单中一个名为name的字段值将会用来初始化Name属性
该字段将会是一个文本字段
字段的标签将会被设置为'name'。
接下来,让我们看一下valid:"MinSize(5);MaxSize(20)"。它指定了两个校验规则:MinSize和MaxSize。效果是,该值至少有5个字符,至多不能超过20个字符。
这里有多个校验规则供你使用,包括区间(Range),Email,IP,Mobile,Base64以及电话号码。
Client string `form:"client,text,client:"` Url string `form:"url,text,url:"`
在上面的两个例子中,Client将会读取表单字段client的值,是一个文本字段,并且字段的标签是client:,Url会读取表单字段url的值,同样是一个文本字段,标签是url:。现在轮到TableName函数了。
我之所以添加它是因为表article的名字和结构体的名字不一致,叫做articles。如果两者一样,Beego的ORM会自动找到它。
但是,我在这里故意修改了名字,因为我想向你演示一下当结构体(struct)和表的名字不一致时该怎么做。现在,我们要讨论一下表的结构。它应该包括下面这些。
CREATE TABLE "articles" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(200) NOT NULL, "client" varchar(100), "url" varchar(400) DEFAULT NULL, "notes" text, UNIQUE (name) );
中奖啦
翻译于 3 个月 前
0人顶
翻译的不错哦!
在应用中整合模型
现在,我们已经建立并配置我们的模型连同随附的表单和验证信息。我们需要让其在我们的应用程序中可用,在main.go中,需多添加三条import语句,如下所示。
"github.com/astaxie/beego/orm" _ "github.com/mattn/go-sqlite3" models "sitepointgoapp/models"
第一条是导入Beego的ORM库,第二条是为了支持sqlite3,被依赖是因为我们使用的是SQLite3数据库。第三条是导入我们刚刚创建的模型,给models一个别名。
func init() {
orm.RegisterDriver("sqlite", orm.DR_Sqlite)
orm.RegisterDataBase("default", "sqlite3", "database/orm_test.db")
orm.RegisterModel(new(models.Article))
}
最后一步我们需要做的是,注册的驱动程序,数据库,以及我们将在我们的应用程序使用的模型。我们用上面的三条语句来这样做这事。我们声明,我们正在使用SQLite的驱动程序,并将其设置为默认的数据库连接,连接到我们的测试数据库,位于indatabase/ orm_test.db。
最后,我们注册我们要使用的模型,在我们的案例中,只需models.Article模型。
AndyLam
翻译于 3 个月 前
1人顶
翻译的不错哦!
CRUD 操作
做好这些,我们现在可以将数据库的支持集成到我们的应用程序中。让我们开始与两个简单的CRUD操作,删除和更新。这些都不使用表单,因为我想保持这一节更注重ORM代码,而不是形式和验证码。我会在后面说道这些。
删除一条记录
我们试图从数据库中基于id删除一篇文章。在Inrouters/routers.go中,向你的function中添加一条:
beego.Router("/manage/delete/:id([0-9]+)", &controllers.ManageController{}, "*:Delete")
然后将代码添加到controllers/manage.go,也就是:
func (manage *ManageController) Delete() {
// convert the string value to an int
articleId, _ := strconv.Atoi(manage.Ctx.Input.Param(":id"))
在这里,我们试图取回id参数,并从String转换成int,然后使用STRCONV包中的Atoi方法就行了。这是一个简单的例子,所以我跳过这可能会引发任何错误,包括acticleId的解析错误。
o := orm.NewOrm()
o.Using("default")
article := models.Article{}似年
翻译于 3 个月 前
1人顶
翻译的不错哦!
接着,我们初始化一个新的ORM实例并确认我们使用了缺省的数据库。我们可以设置任意数量的数据库连接,例如一个用于读,一个用于写等。最后,我们创建一个新的,空的,Article模型实例。
// Check if the article exists first
if exist := o.QueryTable(article.TableName()).Filter("Id", articleId).Exist(); exist {
if num, err := o.Delete(&models.Article{Id: articleId}); err == nil {
beego.Info("Record Deleted. ", num)
} else {
beego.Error("Record couldn't be deleted. Reason: ", err)
}
} else {
beego.Info("Record Doesn't exist.")
}
}
首先,我们查询article表,检查是否有一篇文章的Id和传入的Id参数值匹配。如果存在记录,我们调用ORM的Delete方法,传入文章的Id。
如果没有错误返回,表示文章已经删除,然后调用beego.Info,用Info方法记录删除日志。如果不能删除此记录,将调用Error方法,传入err对象,显示文章不能被删除的原因。
地狱星星
翻译于 3 个月 前
1人顶
翻译的不错哦!
更新一条记录
以上是删除一条记录,现在让我们更新一条记录;这次我将会使用flash信使。
func (manage *ManageController) Update() {
o := orm.NewOrm()
o.Using("default")
flash := beego.NewFlash()
像以前一样,我们初始化一个ORM实例并指定默认数据库。然后我们取得一个Beego Flash对象的句柄,它可以在请求间存储信息。
// convert the string value to an int
if articleId, err := strconv.Atoi(manage.Ctx.Input.Param(":id")); err == nil {
article := models.Article{Id: articleId}
这次我们尝试取得一个id参数并且当它存在时初始化一个新的Article模型。
if o.Read(&article) == nil {
article.Client = "Sitepoint"
article.Url = "http://www.google.com"
if num, err := o.Update(&article); err == nil
{
flash.Notice("Record Was Updated.")
flash.Store(&manage.Controller)
beego.Info("Record Was Updated. ", num)
}
接下来我们调用Read方法,传入这个Article对象,如果有一条记录与Article.Id指定的id相匹配,它会尝试从数据库中加载此article的其他属性。
假设数据库中有这个Id对应的记录,我们在这个article对象上设置了Client和Url属性并且将它传递给了Update方法,它会在数据库中更新这个记录。
--zxp
翻译于 3 个月 前
1人顶
翻译的不错哦!
假设没有发生错误,接下来我们调用Flash对象上的Notice函数并传入一个简单的消息,然后调用Store来持久化这个消息.
} else {
flash.Notice("Record Was NOT Updated.")
flash.Store(&manage.Controller)
beego.Error("Couldn't find article matching id: ", articleId)
}
} else {
flash.Notice("Record Was NOT Updated.")
flash.Store(&manage.Controller)
beego.Error("Couldn't convert id from a string to a number. ", err)
}
如果出了点错,例如不能更新记录或者我们不能将id参数转换成integer类型,我们要在flash信息和log信息中加以标记。
// redirect afterwards
manage.Redirect("/manage/view", 302)
}
最后,我们调用Redirect方法,传入我们要重定向的url和http状态码。这样,不论我们能否更新此记录,我们都会被重定向到/manage/view,在这里我们可以看到定义的结果。
--zxp
翻译于 3 个月 前
2人顶
翻译的不错哦!
查看所有记录
View函数主要有两个目的:首先它需要展示article表中所有已存在的记录,并且还要展示我们在update操作时设置的flash信息,这样我们才能知道操作的成功与否。
func (manage *ManageController) View() {
flash := beego.ReadFromRequest(&manage.Controller)
if ok := flash.Data["error"]; ok != "" {
// Display error messages
manage.Data["errors"] = ok
}
if ok := flash.Data["notice"]; ok != "" {
// Display error messages
manage.Data["notices"] = ok
}
首先我们通过读取请求并查找error与notice两个属性来初始化一个称为flash的变量。这两个属性与flash.Notice和flash.Error的调用相关联。如果已设置了此信息,我们要将其设置到Data属性,这样我们就可以在模板中访问它。
o := orm.NewOrm()
o.Using("default")
var articles []*models.Article
num, err := o.QueryTable("articles").All(&articles)
if err != orm.ErrNoRows && num > 0 {
manage.Data["records"] = articles
}
}
对于最后两个示例,我们建立了一个与默认数据库的连接,并且初始化一个存放Article模型的数组articles。然后调用ORM的QueryTable方法,指定表名,然后调用它的All方法,传入那个articles数组,结果会被加载到articles中,然后就可以访问这些结果了。
如果没有意外的话,我们已经取得了所有可访问的记录并且将它们存储在了模板变量records中。
--zxp
翻译于 3 个月 前
1人顶
翻译的不错哦!
插入一条记录
现在让我们看看在Add action中添加一条记录,包括表单和验证(除了ORM交互)。
func (manage *ManageController) Add() {
o := orm.NewOrm()
o.Using("default")
article := models.Article{}
由于前文已经提及,此处不再赘述。
if err := manage.ParseForm(&article); err != nil {
beego.Error("Couldn't parse the form. Reason: ", err)
} else {
manage.Data["Articles"] = article
此处我们调用ParseForm方法,传入article对象。假设没有异常,我们将article设置为一个模板变量,它会帮我们渲染一个表单,稍后我们会看到。
if manage.Ctx.Input.Method() == "POST" {
valid := validation.Validation{}
isValid, _ := valid.Valid(article)
if !isValid {
manage.Data["Errors"] = valid.ErrorsMap
beego.Error("Form didn't validate.")
} else {
在这我们检查该方法是否使用的POST请求。如果是的话我们要实例化一个新的Validation对象,然后将这个article对象传入它的Valid方法,通过在这个模型上的规则来检查这个POST数据是否合法,
如果提交的数据不合法,我们要存储valid.ErrorsMap,模板变量errors还有验证失败的log中的所有验证错误。否则我们要尝试插入这个article记录。不管是否有错误,我们都要做如下log记录。
id, err := o.Insert(&article)
if err == nil {
msg := fmt.Sprintf("Article inserted with id:", id)
beego.Debug(msg)
} else {
msg := fmt.Sprintf("Couldn't insert new article. Reason: ", err)
beego.Debug(msg)
}
}
}
}--zxp
翻译于 3 个月 前
0人顶
翻译的不错哦!
结尾
我们已经浏览完了Beego。因为这个框架有很多特性,所以在这个只有两部分的系列教程中不可能包含它的所有特性。
另外,在今天的教程中一些示例可能看起来有点奇怪。这样做的原因不是为了好的编码实践,而是为了强调以一种半真实世界的方式实现的功能。这就是你觉得本文有点奇怪的原因。我希望你能享受这篇对Beego的简单介绍,并且希望你能尝试下这个框架。想到到目前为止我在它身上花费的时间,我很享受并打算继续使用它。
如果你有任何疑问,确认查看它的在线文档,也可以在本文提交评论。不要忘记,本文的代码也可以在Github仓库中获得,所以,check出它,然后摆弄并试验下吧。
--zxp
翻译于 3 个月 前
0人顶
翻译的不错哦!
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
Developing a web application with Beego - Part 2
欢迎回到本系列的第二部分,在这我们将用Go的Beego这个web开发框架来加速开发。如果你错过了第一部分,我建议你去读一下,因为它是这一系列的基础。
在第一部分中,我们有了一个好的开始,通过安装Beego及命令行的Bee了解并实际使用了Beego,创建一个基本的项目,添加一个控制行为,创建了一个基本的视图模板,添加一个自定义路由并以学习如何使用请求参数为结尾。
在第二部分中,我们将进入更有趣的部分,构建一个结合数据库的Web应用,使用的是Sqlite3,还要研究一下模型、表单以及验证。我希望你已经准备就绪了,下面让我们一块愉快的走到最后。
Garfielt
翻译于 3 个月 前
0人顶
翻译的不错哦!
两步视图
你会注意到manage控制器里的几个函数,代码如下:
manage.Layout = "basic-layout.tpl" manage.LayoutSections = make(map[string]string) manage.LayoutSections["Header"] = "header.tpl" manage.LayoutSections["Footer"] = "footer.tpl"
这些代码做的是建立了一个两步视图布局。你可能还不熟悉这个术语,它是指你在外部一直显示布局的地方,如侧边栏,导航,header、footer以及那些基于被执行动作的可变内容。
2 Step View Layout
我用上图来说明我的意思。绿色区域是在外部,封装视图和红色部分是基于执行动作内容将要改变的。
通过参考Layout和LayoutSections,我们能够指定外部布局的视图模板,basic-layout.tpl,以及其他的子模板,在我们的例子中为一个header和footer,分别为header.tpl和footer.tpl。
这样做的话,我们行为模板生成的内容将被插入到封装视图模板中,如通过指定{{.LayoutContent}},而header和footer分别为{{.Header}}和{{.Footer}}。
Garfielt
翻译于 3 个月 前
0人顶
翻译的不错哦!
模型
为添加数据库支持,我们需要做的几件事。首先,我们需要建立一些模型。模型基本上只是一些拥有额外信息的结构。下面是一个模型文件,在models/models.go中,我们将在应用的剩余部分中一直使用它。
package models
type Article struct {
Id int `form:"-"`
Name string `form:"name,text,name:" valid:"MinSize(5);MaxSize(20)"`
Client string `form:"client,text,client:"`
Url string `form:"url,text,url:"`
}
func (a *Article) TableName() string {
return "articles"
}
你可以看到里面有一个模型,Article,一个简单的网站文章模型,其包含四个属性: Id, Name, Client 和 Url。你需要注意的是每个属性都有额外的数据,上面提到的form 和valid。
这是将模型用来同时处理生成和验证的一个非常简单的方法。让我们通过实际使用这四个属性解释每个的作用。
Id int `form:"-"`
在我们的数据库中,ID是一个自递增字段。当添加新记录时这个值会自动生成,当删除,更新或查找记录时需要提供这个值。所以对于form:"-",我们要说的是Id不是必需的。
Name string `form:"name,text,name:" valid:"MinSize(5);MaxSize(20)"`
Garfielt
翻译于 3 个月 前
0人顶
翻译的不错哦!
我们这里有一个稍微复杂一些的例子,让我们分解开来,以"name,text,name:"开头。它的意思是当表单被解析的时候,我们将会看到:
来自表单中一个名为name的字段值将会用来初始化Name属性
该字段将会是一个文本字段
字段的标签将会被设置为'name'。
接下来,让我们看一下valid:"MinSize(5);MaxSize(20)"。它指定了两个校验规则:MinSize和MaxSize。效果是,该值至少有5个字符,至多不能超过20个字符。
这里有多个校验规则供你使用,包括区间(Range),Email,IP,Mobile,Base64以及电话号码。
Client string `form:"client,text,client:"` Url string `form:"url,text,url:"`
在上面的两个例子中,Client将会读取表单字段client的值,是一个文本字段,并且字段的标签是client:,Url会读取表单字段url的值,同样是一个文本字段,标签是url:。现在轮到TableName函数了。
我之所以添加它是因为表article的名字和结构体的名字不一致,叫做articles。如果两者一样,Beego的ORM会自动找到它。
但是,我在这里故意修改了名字,因为我想向你演示一下当结构体(struct)和表的名字不一致时该怎么做。现在,我们要讨论一下表的结构。它应该包括下面这些。
CREATE TABLE "articles" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(200) NOT NULL, "client" varchar(100), "url" varchar(400) DEFAULT NULL, "notes" text, UNIQUE (name) );
中奖啦
翻译于 3 个月 前
0人顶
翻译的不错哦!
在应用中整合模型
现在,我们已经建立并配置我们的模型连同随附的表单和验证信息。我们需要让其在我们的应用程序中可用,在main.go中,需多添加三条import语句,如下所示。
"github.com/astaxie/beego/orm" _ "github.com/mattn/go-sqlite3" models "sitepointgoapp/models"
第一条是导入Beego的ORM库,第二条是为了支持sqlite3,被依赖是因为我们使用的是SQLite3数据库。第三条是导入我们刚刚创建的模型,给models一个别名。
func init() {
orm.RegisterDriver("sqlite", orm.DR_Sqlite)
orm.RegisterDataBase("default", "sqlite3", "database/orm_test.db")
orm.RegisterModel(new(models.Article))
}
最后一步我们需要做的是,注册的驱动程序,数据库,以及我们将在我们的应用程序使用的模型。我们用上面的三条语句来这样做这事。我们声明,我们正在使用SQLite的驱动程序,并将其设置为默认的数据库连接,连接到我们的测试数据库,位于indatabase/ orm_test.db。
最后,我们注册我们要使用的模型,在我们的案例中,只需models.Article模型。
AndyLam
翻译于 3 个月 前
1人顶
翻译的不错哦!
CRUD 操作
做好这些,我们现在可以将数据库的支持集成到我们的应用程序中。让我们开始与两个简单的CRUD操作,删除和更新。这些都不使用表单,因为我想保持这一节更注重ORM代码,而不是形式和验证码。我会在后面说道这些。
删除一条记录
我们试图从数据库中基于id删除一篇文章。在Inrouters/routers.go中,向你的function中添加一条:
beego.Router("/manage/delete/:id([0-9]+)", &controllers.ManageController{}, "*:Delete")
然后将代码添加到controllers/manage.go,也就是:
func (manage *ManageController) Delete() {
// convert the string value to an int
articleId, _ := strconv.Atoi(manage.Ctx.Input.Param(":id"))
在这里,我们试图取回id参数,并从String转换成int,然后使用STRCONV包中的Atoi方法就行了。这是一个简单的例子,所以我跳过这可能会引发任何错误,包括acticleId的解析错误。
o := orm.NewOrm()
o.Using("default")
article := models.Article{}似年
翻译于 3 个月 前
1人顶
翻译的不错哦!
接着,我们初始化一个新的ORM实例并确认我们使用了缺省的数据库。我们可以设置任意数量的数据库连接,例如一个用于读,一个用于写等。最后,我们创建一个新的,空的,Article模型实例。
// Check if the article exists first
if exist := o.QueryTable(article.TableName()).Filter("Id", articleId).Exist(); exist {
if num, err := o.Delete(&models.Article{Id: articleId}); err == nil {
beego.Info("Record Deleted. ", num)
} else {
beego.Error("Record couldn't be deleted. Reason: ", err)
}
} else {
beego.Info("Record Doesn't exist.")
}
}
首先,我们查询article表,检查是否有一篇文章的Id和传入的Id参数值匹配。如果存在记录,我们调用ORM的Delete方法,传入文章的Id。
如果没有错误返回,表示文章已经删除,然后调用beego.Info,用Info方法记录删除日志。如果不能删除此记录,将调用Error方法,传入err对象,显示文章不能被删除的原因。
地狱星星
翻译于 3 个月 前
1人顶
翻译的不错哦!
更新一条记录
以上是删除一条记录,现在让我们更新一条记录;这次我将会使用flash信使。
func (manage *ManageController) Update() {
o := orm.NewOrm()
o.Using("default")
flash := beego.NewFlash()
像以前一样,我们初始化一个ORM实例并指定默认数据库。然后我们取得一个Beego Flash对象的句柄,它可以在请求间存储信息。
// convert the string value to an int
if articleId, err := strconv.Atoi(manage.Ctx.Input.Param(":id")); err == nil {
article := models.Article{Id: articleId}
这次我们尝试取得一个id参数并且当它存在时初始化一个新的Article模型。
if o.Read(&article) == nil {
article.Client = "Sitepoint"
article.Url = "http://www.google.com"
if num, err := o.Update(&article); err == nil
{
flash.Notice("Record Was Updated.")
flash.Store(&manage.Controller)
beego.Info("Record Was Updated. ", num)
}
接下来我们调用Read方法,传入这个Article对象,如果有一条记录与Article.Id指定的id相匹配,它会尝试从数据库中加载此article的其他属性。
假设数据库中有这个Id对应的记录,我们在这个article对象上设置了Client和Url属性并且将它传递给了Update方法,它会在数据库中更新这个记录。
--zxp
翻译于 3 个月 前
1人顶
翻译的不错哦!
假设没有发生错误,接下来我们调用Flash对象上的Notice函数并传入一个简单的消息,然后调用Store来持久化这个消息.
} else {
flash.Notice("Record Was NOT Updated.")
flash.Store(&manage.Controller)
beego.Error("Couldn't find article matching id: ", articleId)
}
} else {
flash.Notice("Record Was NOT Updated.")
flash.Store(&manage.Controller)
beego.Error("Couldn't convert id from a string to a number. ", err)
}
如果出了点错,例如不能更新记录或者我们不能将id参数转换成integer类型,我们要在flash信息和log信息中加以标记。
// redirect afterwards
manage.Redirect("/manage/view", 302)
}
最后,我们调用Redirect方法,传入我们要重定向的url和http状态码。这样,不论我们能否更新此记录,我们都会被重定向到/manage/view,在这里我们可以看到定义的结果。
--zxp
翻译于 3 个月 前
2人顶
翻译的不错哦!
查看所有记录
View函数主要有两个目的:首先它需要展示article表中所有已存在的记录,并且还要展示我们在update操作时设置的flash信息,这样我们才能知道操作的成功与否。
func (manage *ManageController) View() {
flash := beego.ReadFromRequest(&manage.Controller)
if ok := flash.Data["error"]; ok != "" {
// Display error messages
manage.Data["errors"] = ok
}
if ok := flash.Data["notice"]; ok != "" {
// Display error messages
manage.Data["notices"] = ok
}
首先我们通过读取请求并查找error与notice两个属性来初始化一个称为flash的变量。这两个属性与flash.Notice和flash.Error的调用相关联。如果已设置了此信息,我们要将其设置到Data属性,这样我们就可以在模板中访问它。
o := orm.NewOrm()
o.Using("default")
var articles []*models.Article
num, err := o.QueryTable("articles").All(&articles)
if err != orm.ErrNoRows && num > 0 {
manage.Data["records"] = articles
}
}
对于最后两个示例,我们建立了一个与默认数据库的连接,并且初始化一个存放Article模型的数组articles。然后调用ORM的QueryTable方法,指定表名,然后调用它的All方法,传入那个articles数组,结果会被加载到articles中,然后就可以访问这些结果了。
如果没有意外的话,我们已经取得了所有可访问的记录并且将它们存储在了模板变量records中。
--zxp
翻译于 3 个月 前
1人顶
翻译的不错哦!
插入一条记录
现在让我们看看在Add action中添加一条记录,包括表单和验证(除了ORM交互)。
func (manage *ManageController) Add() {
o := orm.NewOrm()
o.Using("default")
article := models.Article{}
由于前文已经提及,此处不再赘述。
if err := manage.ParseForm(&article); err != nil {
beego.Error("Couldn't parse the form. Reason: ", err)
} else {
manage.Data["Articles"] = article
此处我们调用ParseForm方法,传入article对象。假设没有异常,我们将article设置为一个模板变量,它会帮我们渲染一个表单,稍后我们会看到。
if manage.Ctx.Input.Method() == "POST" {
valid := validation.Validation{}
isValid, _ := valid.Valid(article)
if !isValid {
manage.Data["Errors"] = valid.ErrorsMap
beego.Error("Form didn't validate.")
} else {
在这我们检查该方法是否使用的POST请求。如果是的话我们要实例化一个新的Validation对象,然后将这个article对象传入它的Valid方法,通过在这个模型上的规则来检查这个POST数据是否合法,
如果提交的数据不合法,我们要存储valid.ErrorsMap,模板变量errors还有验证失败的log中的所有验证错误。否则我们要尝试插入这个article记录。不管是否有错误,我们都要做如下log记录。
id, err := o.Insert(&article)
if err == nil {
msg := fmt.Sprintf("Article inserted with id:", id)
beego.Debug(msg)
} else {
msg := fmt.Sprintf("Couldn't insert new article. Reason: ", err)
beego.Debug(msg)
}
}
}
}--zxp
翻译于 3 个月 前
0人顶
翻译的不错哦!
结尾
我们已经浏览完了Beego。因为这个框架有很多特性,所以在这个只有两部分的系列教程中不可能包含它的所有特性。
另外,在今天的教程中一些示例可能看起来有点奇怪。这样做的原因不是为了好的编码实践,而是为了强调以一种半真实世界的方式实现的功能。这就是你觉得本文有点奇怪的原因。我希望你能享受这篇对Beego的简单介绍,并且希望你能尝试下这个框架。想到到目前为止我在它身上花费的时间,我很享受并打算继续使用它。
如果你有任何疑问,确认查看它的在线文档,也可以在本文提交评论。不要忘记,本文的代码也可以在Github仓库中获得,所以,check出它,然后摆弄并试验下吧。
--zxp
翻译于 3 个月 前
0人顶
翻译的不错哦!
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们