beego开发轻博客——第五讲 文章录入

qq归位 · · 1687 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

【小鸡软件】beego开发轻博客

本章目标:添加文章录入功能
github: 打开后,点击右上角star按钮
码云: 打开后,点击右上角star按钮


前台页面

1. 我们采用“ wangeditor”作为 富文本编辑器 编辑器

wangEditor 是一款 轻量级 web 富文本编辑器。配置方便,使用简单。支持 IE10+ 浏览器。

2 新增 views->note_new.html 文件,核心代码如下
<body class="lay-blog">
        ...
    <form class="layui-form layui-form-pane" action="">
        <div class="layui-form-item">
            <label class="layui-form-label">标题</label>
            <div class="layui-input-block">
                <input type="text" name="title" required=""
                        value=""
                        lay-verify="required" placeholder="请输入标题"
                        autocomplete="off" class="layui-input">
            </div>
        </div>

        <div class="layui-form-item layui-form-text">
            <label class="layui-form-label">内容</label>
            <div class="layui-input-block">
                <div id="edit"></div>
            </div>
        </div>
        <div class="layui-form-item">
            <button class="layui-btn" lay-submit=""
                    lay-filter="save">提交
            </button>
        </div>
    </form>
       ...

页面效果如下:
image.png
3. wangEditor使用

我们只需要引入wangEditor.min.js 文件,调用window.wangEditor("元素id").create() 就可 初始化富文本页面 。我继续修改views->note_new.html 文件。

<body>
...
<form>... <div id="edit"><div> ...</form>
...
{{template "comm/footer.html" .}}
<script type="text/javascript" src="/static/lib/wangEditor/wangEditor.min.js"></script>
<script>
    layui.use([...], function () {
        ...
        // 初始化 wangEditor
        var E = window.wangEditor;
        var editor = new E('#edit');
      // 图片不采用上传模式,直接保存到数据库
        editor.customConfig.uploadImgShowBase64 = true;
        editor.customConfig.pasteFilterStyle = false;
        editor.customConfig.zIndex = 1;
        editor.create();
    });
</script>

定义数据库表

新增models->note.go 定义文章表,代码如下
type Note struct {
    gorm.Model
    Key     string `gorm:"unique_index;not null;"` //文章唯一标示
    UserID  int // 用户id
    User    User  //用户
    Title   string //文章标题
    Summary string `gorm:"type:text"` //概要
    Content string `gorm:"type:text"` //文章内容
    Visit   int    `gorm:"default:0"` //浏览次数
    Praise  int    `gorm:"default:0"` // 点赞次数
}

新增文章的页面显示

1. 我们需要为文章新增页面添加路由路径,以此我们新增一个新的NoteController控制器。新增 controllers->note.go文件添加如下代码
type NoteController struct {
    BaseController
}
// @router /new [get]
func (ctx *NoteController) NewPage() {
    ctx.Data["key"] = uuid.NewUUID().String()
    ctx.TplName = "note_new.html"
}

上面代码中有个ctx.Data["key"] = uuid.NewUUID().String()。试想如果用户打开新增文章页面后,维护好数据,当点击保存按钮时候,不小心多点几次,难道系统就会多新增几个重复的文章记录?因此,我们添加了ctx.Data["key"] = uuid.NewUUID().String() 使每打开新增文章页面都会有一个唯一的key 在当前页面上。当点击保存时,会将页面key传回到后台,这样后台可以更具key开判断用户是新增还是修改!刚才说的情况用户多次点击,第一次是新增,之后都是修改。

2. 与文章调整相关的功能,必须是登陆的用户,且登陆的用户的必须是管理员。我们修改 NoteController控制器,添加NestPrepare方法。每次发送的请求,当路由到NoteController控制器相应的方法时,都会去调用NestPrepare方法,用来添加判断用户必须登陆且为管理员。修改controllers->note.go,代码如下
func (ctx *NoteController) NestPrepare() {
    ctx.MustLogin()//用户必须登陆,没有登陆就返回错误
    if ctx.User.Role != 0 {//不是管理员,之前返回错误
        ctx.Abort500(syserrors.NewError("您没有权限修改文章", nil))
    }
}
3. 我们采用的beego的注解路由,我需要将NoteController控制器 注入beego的Include上。修改routers->router.go文件,修改如下:
func init() {
    ...
    beego.AddNamespace(
        beego.NewNamespace(
            "note",
            beego.NSInclude(&controllers.NoteController{}),
        ),
    )
}

到此,新增文章的路由路径为:note/new

4. 添加新增文章的操作入口->修改用户管理页面(views->user.html) 添加按钮,点击跳转到文章新增页面。修改views->user.html文件,修改代码如下:
...
{{if .IsLogin}}
    ...
  {{if eq .User.Role 0}}
    <h4 class="item-title">
        <p>
            <a href="/note/new"><i class="layui-icon layui-icon-add-1">&#xe654;</i><span>新增文章</span></a>
        </p>
    </h4>
{{end}}
...

新增文章的页面保存功能

1. 我们新约定 文章新增的路由路径为:/note/save/:key
2. 添加页面逻辑,当保存时,我们将页面用户维护的文章数据用ajax发送post请求到后台服务,服务对于的路径为/note/save/:key,我们需要修改views->note_new.html文件,添加如下代码
...
<script>
    layui.use(['form', 'jquery', 'layer', 'sysn'], function () {
        ...
      form.on('submit(save)', function (fromdata) {
        sysn.post("/note/save/{{.key}}", fdata)
            .success(function (data) {
               layer.msg("保存成功!");
               if (data.action) {
                    setTimeout(function () {
                         window.location.href = data.action;
                    }, 300)
               }
            }).run();
      }
}
</script>
...
3. 调整数据库

3.1 我们之前定义的文章的数据库中表结构中key是不能重复的,是作为文章的唯一标示。因此我们新增的时候都需要先判断 key是否存在,如果存在就更新不存在就新增。我们修改models->note.go 添加按key查询文章的方法。

func QueryNoteByKeyAndUserId(key string, userid int) (note Note, err error) {
    return note, db.Model(&Note{}).Where("key = ? and user_id = ?", key, userid).Take(&note).Error
}

3.2 需要将文章的数据保存到数据库,因此我们要新增方法,用来保存文章数据。代码如下:

func SaveNote(n *Note) error {
    return db.Save(n).Error
}
4. 调整控制器NoteController

4.1 将来我们需要将文章在首页列出来,我们不能将文章的所有的内容都显示在首页,因此我们需要截取文章前600个字作为文章的摘要保存到数据库。这里我们用到golang的第三方库github.com/PuerkitoBio/goquery,用来解析文章的html文档。修改controllers->note.go 添加截取文章摘要的方法,代码如下。

// 截取content摘要
//content >文章 > html文档
func getSummary(content string) (string, error) {
   // bytes.Buffer,非常常用。
    var buf bytes.Buffer
    buf.Write([]byte(content))
    // 用goquery来解析content
    doc, err := goquery.NewDocumentFromReader(&buf)
    if err != nil {
        return "", err
    }
    // Text() 得到body元素下的文本内容(去掉html元素)
    str := doc.Find("body").Text()
    // 截取字符串
    if len(str) > 600 {
        str = str[0:600] + "..."
    }
    return str, nil
}

4.1 新增保存文章的方法 ,修改controllers->note.go ,代码如下

// @router /save/:key [post]
func (ctx *NoteController) Save() {
    //得到页面的传过来 key 
    key := ctx.Ctx.Input.Param(":key")
    // 判空,为空就返回错误。
    title := ctx.GetMustString("title", "标题不能为空!")
    content := ctx.GetMustString("content", "内容不能为空!")
    //获取文章摘要
    summary, _ := getSummary(content)
    // 根据key查询文章
    note, err := ctx.Dao.QueryNoteByKeyAndUserId(key, int(ctx.User.ID))
    var n models.Note
    if err != nil {
        //存在错误,但是当错误不是查不到数据的错误,那就返回错误
        if err != gorm.ErrRecordNotFound {
            ctx.Abort500(syserrors.NewError("保存失败!", err))
        }
       // 查不到数据,那就做新增文章操作
        n = models.Note{
            Key:     key,
            Summary: summary,
            Title:   title,
            Files:   files,
            Content: content,
            UserID:  int(ctx.User.ID),
        }
    } else {
        //查询不报错,这存在文章,那就做更新文章操作
        n = note
        n.Title = title
        n.Content = content
        n.Summary = summary
        n.Files = files
        n.UpdatedAt = time.Now()
    }
    //保存文章 SaveNote 是根据id来判断是更新还是新增,id存在就更新,不存在就新增。
   //上面更新操作是,从数据库查出来的文章记录,修改数据,所以是存在id的。
    if err := ctx.Dao.SaveNote(&n); err != nil {
        ctx.Abort500(syserrors.NewError("保存失败!", err))
    }
    ctx.JSONOk("成功")
}

用户保存文章功能,我们已经完成


总结

本讲,我们实现了文章录入的功能,我们回顾下实现过程共分为两大步骤:
  1. 第一步 准备工作
    1.1 画出文章的新增的页面。
    1.2 设计好文章的数据库表结构。
    1.3 添加路由让 1.1 的新增的页面,可以访问到。
  2. 第二步 实现文章保存
    2.1 修改新增页面,保存时向后台发送请求。
    2.2 实现后台的逻辑,保存数据到数据库。

下一讲,我们将会实现文章显示、文章修改和文章删除的功能。下讲再见????


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:qq归位

查看原文:beego开发轻博客——第五讲 文章录入

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1687 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传