beego开发轻博客——第七讲 文章的显示、修改与删除

【小鸡创作】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(&note).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: '&#xe642;',//编辑的图标
            bar2:'&#xe640;'  //删除的图标
            ,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("网络异常")
                });
            }
            ...
});

文章删除的功能已经实现。
这儿可以考虑优化一下删除文章的时候提示是否删除


贴个页面效果图

文章显示效果图

广告:

  1. 本专集也做了视频教程 : B站地址 ,前期可能视频和专集有的细微差别,望大家谅解。欢迎大家关注。
  2. 最近做几个视频,欢迎大家观赏!这些视频源码:github仓库
    B站001B站002B站002B站004
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容