【小鸡创作】beego开发轻博客
本章目标:添加“文章的显示、修改与删除”功能
github: 打开后,点击右上角star按钮
视频教程: B站地址
文章显示
1. 功能分析
文章的显示功能,首先我们需要添加路由,约定文章显示的路由路径为"/details/[文章的key]",再添加路由对应的控制器,我们需要根据key查找到文章的记录,返回给页面。
根据文字的key查询文章的数据库方法,我们之前在新增文章的时候已经添加。
2. 控制器逻辑调整
2.1 修改controllers->index.go添加GetDetails,查询文章信息返回给页面,代码如下(请留意代码中的注解,都是逻辑说明):
//@router /details/:key [get]
func (this *IndexController) GetDetails() {
//得到页面传过来的文章的key
key:= this.Ctx.Input.Param(":key")
//到数据库中根据key查询文章
note,err:=models.QueryNoteByKey(key)
if err!=nil{
//查询有问题,就提示页面文章不存在
this.Abort500(syserror.New("文章不存在",err))
}
//将文章的信息放回给页面
this.Data["note"] = note
this.TplName="details.html"
}
3. 前台页面调整
3.1 我们修改views->index.html 页面,修改跳转文章详情的链接,改成我们定义好的路由路径。修改代码如下
...
<div class="item-box layer-photos-demo1 layer-photos-demo">
<!-- 此处拼写 文章详情路由路径 -->
<h3><a href="details/{{.Key}}">{{.Title}}</a></h3>
<h5>发布于:<span>{{date .UpdatedAt "Y-m-d H:i:s"}}</span></h5>
...
3.1 我们修改views->index.html 页面,将文章摘要信息显示的部分抽取出来保存为模版,并且新增文件views->comm->note_summary_tpl.html。
3.1.1 views->index.html 修改代码如下
{{ range .notes}}
<div class="item">
{{template "comm/note_summary_tpl.html" .}}
<div class="comment count">
...
</div>
{{end}}
3.1.2 views->comm->note_summary_tpl.html修改代码如下
<div class="item-box layer-photos-demo1 layer-photos-demo">
<h3><a href="details/{{.Key}}">{{.Title}}</a></h3>
<h5>发布于:<span>{{date .UpdatedAt "Y-m-d H:i:s"}}</span></h5>
<p>{{.Summary}}</p>
</div>
3.2 我们复制文件views->comm->note_summary_tpl.html保存为views->comm->note_tpl.html修改其中的代码将显示文章摘要改成显示文章的内容,修改代码如下
...
<!--原代码是:<p>{{.Summary}}</p>-->
<!--go的html模版输出默认是对html标签转义的-->
<!--str2html是beego提供的方法,可以将字符串直接输出不转义-->
<p>{{str2html .Content}}</p>
...
3.3 我们修改views->details.html 页面,嵌入views->comm->note_tpl.html模版页面,显示文章内容,修改代码如下
...
<div class="item-box layer-photos-demo1 layer-photos-demo">
<!--此处为修改-->
<!--请注意 后面传的是.note作为通道传给模版-->
{{template "comm/note_tpl.html" .note }}
<div class="count layui-clear">
...
文章的显示功能已经实现
文章修改
1. 功能分析
1、我们需要给文章修改功能添加操作入口,我们使用layui提供的fixbar作为操作按钮。
2、页面需要的数据:我们要判断用户是否登陆,用户是否有修改文章的权限,同时我们也有判断当前的用户id是否和当前文章所属用户的id相等,只有满足这些条件才能对文章进行修改和删除的操作。修改文章时我们需要带入文章的key。因此我们要拿到当前登陆的用户的信息,还要拿到当前文章详情页面的文章的所属用户的id和文章的key值。
3、页面要拿到当前登陆的用户的信息,我们要将用户信息保存到html页面中类型为json对象的user变量。为了得到user的json对象,我们需要定义“gorm定义表结构的结构体”的json输出的格式。
4、我们定义修改文章的路由路径为:/edit/[当前文章的key],然后路由对应的控制器方法的逻辑是:根据key和当前登陆的用户找到文章数据(这儿我们需要新增数据库方法),指定渲染模版note_new.html,修改note_new.html,使其能够显示文章具体信息。而note_new.html模版,在文章新增的时候,我们就已经支持文章修改的功能,我们只需修改文章保存的控制器方法,添加保存后返回的跳转页面路径,跳转到文章详情页面。
2. 数据库逻辑调整
2.1 添加根据用户id和文章的key查询文章的方法,修改models->note.go文件,添加QueryNoteByKeyAndUserId方法,代码如下:
func QueryNoteByKeyAndUserId(key string, userid int) (note Note, err error) {
return note, db.Where("key = ? and user_id = ? ", key, userid).Take(¬e).Error
}
2.2 目前定义数据库表结构的结构体都是继承gorm自带的model结构体,而gorm的model的结构体,没法重新定义json输出的格式,因此,我们重新定义model的结构体并定义json的格式。修改models->core.go文件,添加代码如下
// `json:"name"` 这句是定义json输出的格式
type Model struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `sql:"index" json:"deleted_at"`
}
2.3 修改models->note.go,修改代码如下
type Note struct {
Model//这儿的Model是我们上面定义的Model不是gorm.Model
...
}
2.4 修改models->user.go,优化用户结构体的json输出的格式,修改代码如下
type User struct {
Model //这儿的Model是我们上面定义的Model不是gorm.Model
Name string `gorm:"unique_index" json:"name"`
Email string `gorm:"unique_index" json:"email"`
Pwd string `json:"-"`//“-” 代表不输出,密码不能输出到页面。
Avatar string `json:"avatar"`
Role int `json:"role"`
}
3. 控制器逻辑调整
3.1 添加编辑页面的路由/edit/:key,添加控制器逻辑:查询文章并显示文章修改页面。修改controllers->note.go文件,添加如下代码:
// @router /edit/:key [get]
func (this *NoteController) EditPage() {
// 获取页面传过来key
key := this.Ctx.Input.Param(":key")
//根据当前文章的key和登陆用户id查询出,文章信息。
note, err := models.QueryNoteByKeyAndUserId(key, int(this.User.ID))
if err != nil {
//查询有问题,就提示文章不存在。
this.Abort500(syserror.New("文章不存在!", err))
}
//将文章的信息以及key传到页面。
this.Data["note"] = note
this.Data["key"] = key
//"note_new.html" 是文章新增的页面,之前实现文章新增功能的时候
this.TplName = "note_new.html"
}
3.2 修改文章保存的控制器逻辑,让页面保存成功后跳转页面到文章详情页面。修改controllers->note.go中的Save方法。
// @router /save/:key [post]
func (this *NoteController) Save() {
...
//原代码:this.JSONOkH("保存成功", H{})
this.JSONOk("保存成功", fmt.Sprintf("/details/%s", key))
}
4. 前台页面调整
4.1 在文章详情页面中,我们将当前登陆的用户信息,文章的用户所属id,以及文章的key,保存到js变量中。修改views->details.html页面添加如下代码
<script>
var user = {{.User}};//这儿输出直接就是json对象
//这儿将文章的信息拼成json对象赋值给note变量
var note = { userid:{{.note.UserID}},key:{{.note.Key}} };
</script>
4.2 在文章详情页面添加修改和删除的操作按钮,我们采用layui提供的fixbar控件,同时我们根据当前登陆的用户和当前文章详情页的文章的所属用户来判断是否显示按钮,修改views->details.html页面添加如下代码
<script>
...
layui.use(['util','jquery'], function(){
var util = layui.util,$= layui.jquery;
//用户必须登陆,
//登陆的用户的role必须为0,可以修改文章
//登陆的用户的id,必须等于当前文章详情页的文章所属用户的id
if(user&& user.id >0&&user.role===0&&user.id ===note.userid){
util.fixbar({
bar1: '',//编辑的图标
bar2:'' //删除的图标
,click: function(type){
console.log(type);
if(type === 'bar1'){
//跳转到修改文章的页面
window.location.href="/note/edit/"+note.key
}
if(type === 'bar2'){
//删除的逻辑,等待实现。
}
}
});
}
});
</script>
4.3 文章修改的页面views-note_new.html页面,虽然之前实现了修改文章的功能。页面模版没有根据传过来的文章内容来填充文章的内容。我们修改views-note_new.html 修改代码如下
...
<form class="layui-form layui-form-pane" action="">
...
<!--{{/* 修改代码为: value="{{.note.Title}}" */}}-->
<div class="layui-input-block">
<input type="text" name="title" required=""
value="{{.note.Title}}"
lay-verify="required" placeholder="请输入标题"
autocomplete="off" class="layui-input">
...
<!--{{/* 修改代码为: {{if .note}}{{str2html .note.Content}}{{end}} */}}-->
<div id="edit"
style="background: #fff;">
{{if .note}}{{str2html .note.Content}}{{end}}
</div>
</div>
</div>
...
</form>
文章修改功能已经实现
文章删除
1. 功能分析
我们需要定义文章删除功能的路由定义:/del/[文章的key] 为post请求。我们要添加根据用户id和文章的key去删除文章的数据库方法。再添加路由对应的控制器逻辑,调用删除文章的数据库方法来删除文章。修改文章详情页面,当点击删除按钮的时候,后台发送post请求,成功提示删除成功,页面跳转到首页。失败就提示删除失败。
2. 数据库逻辑调整
2.1 修改models-note.go文件,我们添加根据用户id和文章的key,删除文章的方法,代码如下
func DeleteNoteByUserIdAndKey(key string, userid int) error {
return db.Delete(&Note{}, "key = ? and user_id = ?", key, userid).Error
}
3. 控制器逻辑调整
3.1 修改controllers-note.go文件,添加根据传过来的key和当前登陆的用户id 去调用删除文章的控制器方法,代码如下
// @router /del/:key [post]
func (this *NoteController) Del() {
//获取页面传过来的key值
key := this.Ctx.Input.Param(":key")
//调用数据库方法删除文章
if err := models.DeleteNoteByUserIdAndKey(key, int(this.User.ID)); err != nil {
//删除失败,提示页面删除失败
this.Abort500(syserror.New("删除失败", err))
}
//返回删除成功,并跳转到首页
this.JSONOk("删除成功", "/")
}
4. 前台页面调整
4.1 修改views->details.html文件,添加向后台发送删除文章的请求的逻辑,添加代码如下
layui.use(['util','jquery'], function(){
...
if(type === 'bar2'){
$.post("/note/del/"+note.key,function (data) {
if (data.code === 0) {
layer.msg("删除成功");
if (data.action) {
setTimeout(function () {
window.location.href = data.action;
}, 300);
}
} else {
layer.msg("删除失败:" + data.msg);
}
}, "json").error(function () {
layer.msg("网络异常")
});
}
...
});
文章删除的功能已经实现。
这儿可以考虑优化一下删除文章的时候提示是否删除
网友评论