分享

评论和留言板功能

 心平9bwburua3p 2017-04-14

评论和留言功能实现

实验说明

这一节实验中,主要讲解怎么样实现博客的评论和留言功能。

本实验属于实验楼课程《基于Reve和mgo的博客》,该课程基于joveth的教程Go web开发之revel+mgo改编而来。具体来说,在joveth教程的基础上,实验楼修改了教程以适配最新版本的Revel

为了能正常开始实验,我们需要设置 GOPATH 环境变量以及启动mongodb,每次开始实验前,请执行以下命令:

$ cd /home/shiyanlou/revel_mgo_blog
$ export GOPATH=`pwd`
$ export PATH=$PATH:$GOPATH/bin
$ sudo mongod --fork -f /etc/mongodb.conf

全局样式

为了方便使用,这里将整个项目的css贴出,将以下内容写入到/home/shiyanlou/revel_mgo_blog/src/GBlog/public/css/styles.css 中:

    body{
      margin: 0 auto;
      padding: 0;
      font: 14px "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
      line-height: 20px;
      letter-spacing: 0.02em;
      color: #666;
      background-attachment:fixed;
    }
    a{
      color: #1abc9c;
      text-decoration: none;
      -webkit-transition: 0.25s;
      -moz-transition: 0.25s;
      -o-transition: 0.25s;
      transition: 0.25s;
      -webkit-backface-visibility: hidden;
    }
    .main-nav{
      margin: 0 auto;
      width: 692px;
      padding:0;
    }
    .top-bar{
      width:100%;
      background: #34495e;
      border-bottom-right-radius: 6px;
      border-bottom-left-radius: 6px;
      box-shadow:  0 2px rgba(0,0,0,0.075),0 0 6px #7aba7b;
      -webkit-box-shadow:0 2px  rgba(0,0,0,0.075),0 0 6px #7aba7b;
      -moz-box-shadow:0 2px  rgba(0,0,0,0.075),0 0 6px #7aba7b;
      margin-bottom:28px;
    }
    .top-bar-inner{
      min-height: 48px;
      padding:0 4px;
    }
    .ul-nav{
      position: relative;
      left: 0;
      display: block;
      float: left;
      margin: 0 10px 0 0;
      list-style: none;
      font-size: 18px;
      padding:0;
    }
    .ul-nav>li {
      position: relative;
      float: left;
      line-height: 20px;
    }
    .ul-nav>li>a{
      padding: 14px 24px 17px;
      text-decoration: none;
      display: block;
      color: white;
      text-shadow: 0 -1px 0 rgba(0,0,0,0.25);
    }
    .ul-nav>li>a:hover,.ul-nav>li>a:focus{
      color: #1abc9c;
    }
    .navbar-news {
      background-color: #e74c3c;
      border-radius: 30px;
      color: white;
      display: block;
      font-size: 12px;
      font-weight: 500;
      line-height: 18px;
      min-width: 8px;
      padding: 0 5px;
      position: absolute;
      right: -7px;
      text-align: center;
      text-shadow: none;
      top: 8px;
      z-index: 10;
    }
    .ul-nav .active > a, .ul-nav .active > a:hover, .ul-nav .active > a:focus {
      background-color: transparent;
      color: #1abc9c;
      -webkit-box-shadow: none;
      -moz-box-shadow: none;
      box-shadow: none; 
    }
    .cell{
      background-color:#1bc6a5;
      color: #cff3ec;
      font-size: 15px;
      border-radius: 4px;
      -webkit-border-radius: 4px;
      -moz-border-radius: 4px;
      -o-border-radius: 4px;
      -khtml-border-radius: 4px;
      padding: 18px 20px 0px 20px; 
      margin-bottom: 30px;
      box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);

    }
    .cell-subject{
      margin: 0;
    }
    .cell-subject-title{
      color: #34495e;
      font-size: 24px;
      font-weight: 700;
      text-decoration: none;
    }
    a.cell-subject-title:hover{
      text-decoration: underline;
    }
    .subject-infor{
      color:#34495e;
      line-height: 19px;
      padding: 2px 0;
      font-size: 13px;
      margin:2px 0;
    }
    .cell-text{
      padding: 4px 0;
      word-break: break-all;
    }
    .comment-num{
      float:right;
      border: 5px solid #d7dce0;
      border-radius: 50px;
      font-size: 14px;
      line-height: 16px;
      padding: 0 4px;
      -webkit-transition: background 0.2s ease-out, border-color 0s ease-out, color 0.2s ease-out;
      -moz-transition: background 0.2s ease-out, border-color 0s ease-out, color 0.2s ease-out;
      -o-transition: background 0.2s ease-out, border-color 0s ease-out, color 0.2s ease-out;
      transition: background 0.2s ease-out, border-color 0s ease-out, color 0.2s ease-out;
      -webkit-backface-visibility: hidden;
      background-color: white;
      border-color: white;
      border-width: 2px;
      color: #BBB6B6;
    }
    .write-nav{
      padding: 10px;
      background-color: #f9f9f9;
      border: 1px solid #e4e4e4;
      border-radius: 5px;
    }
    .footer{
      margin:20px 0 10px 0;
      text-align: center;
      min-height: 20px;
    }
    .comment-nav,.history-nav{
      background-color: white;
      border: 1px solid #DDD;
      border-radius: 4px;
    }
    .comment-title,.history-title{
      padding: 10px 20px;
      border-bottom: 1px solid #e2e2e2;
      font-size: 15px;
      font-weight: bold;
    }
    .comment-cell{
      padding: 10px 10px;
      border-top: 2px solid #fff;
      border-bottom: 1px solid #e2e2e2;
    }
    .comment-inputbox{
      background-color: #E7E7D8;
      border: 1px solid #d6d6c6;
      padding:5px 10px;
      border-radius: 8px;
      height: 224px;

    }
    .comment-input-infor{
      float: left;
      width: 180px;
      height: 200px;
      display: inline;
      overflow: hidden;
      margin:5px 0  0 0;
      list-style: none;
      padding:0;
    }

    .comment-input-text{
      float: left;
      width: 458px;
      height: 150px;
      margin:5px 0  0 10px;
    }
    .ctextarea {
      height: 142px !important;
      resize: vertical;
    }
    .comment-input-text-btn{
      float:right;
      margin-top:20px;
    }
    .func-color{
      color: #F70246;
    }
    .func-name{
      color: #24C54B;
    }
    .func-str{
      color:#C29916;
    }
    .func-type{
      color:rgb(0, 173, 255);
    }
    .pln-w{
      color:white;
    }
    .pln-b{
      color:white;
    }
    .history-cell{
      padding: 10px 20px;
      border-top: 2px solid #fff;
      border-bottom: 1px solid #e2e2e2;
    }
    li time{
      margin-right: 8px;
      font-size: 13px;
    }
    .history-auth{
      padding-left: 8px;
      color: #cfcfcf;
      font-size: 13px;
      font-family: 'Microsoft Yahei';
    }
    .email-other{
      background-color: #f9f9f9;
      border: 1px solid #e4e4e4;
      border-radius: 5px;
      padding: 5px 20px;
      margin-bottom: 10px;
    }
    .email-title{
      margin: 0 0 22px;
      padding-top: 21px;
      color: white;
      font-family: 'Microsoft Yahei';
    }
    .email-nav ul{
      list-style-type: none;
      margin: 0 0 26px;
      padding:0;
    }
    .email-nav ul li:first-child {
      border-top: none;
      padding-top: 1px;
    }
    .email-nav ul li {
      border-top: 1px solid #1bc6a5;
      line-height: 19px;
      padding: 6px 0;
    }
    .email-tag{
      border-radius: 4px;
      background: #1abc9c;
      color: white;
      cursor: pointer;
      margin-right: 5px;
      margin-bottom: 5px;
      overflow: hidden;
      padding: 6px 13px 6px 19px;
      position: relative;
      vertical-align: middle;
      display: inline-block;
      zoom: 1;
      -webkit-transition: 0.14s linear;
      -moz-transition: 0.14s linear;
      -o-transition: 0.14s linear;
      transition: 0.14s linear;
      -webkit-backface-visibility: hidden;
    }
    .email-tag span{
      color: white;
      cursor: pointer;
      zoom: 1;
    }
    .email-nav{
      background: white;
      border: 2px solid #1abc9c;
      border-radius: 6px;
      padding: 6px 1px 1px 6px;
      overflow-y: auto;
      text-align: left;
      margin-bottom: 15px;
    }
    .email-tag:hover {
      background-color: #16a085;
      padding-left: 12px;
      padding-right: 20px;
    }
    .erro{
      color:red;
    }
    .infor-content,.comments{
      margin-bottom: 20px;
      padding: 10px 20px;
      background-color: white;
      border: 1px solid #DDD;
      border-radius: 4px;
      -webkit-border-radius: 4px;
      -moz-border-radius: 4px;
      -o-border-radius: 4px;
      -khtml-border-radius: 4px;
    }
    .infor-header{
      padding-bottom: 9px;
      margin: 0 0 20px;
      border-bottom: 1px solid #eee;
    }
    .infor-header h3{
      margin-top:10px;
    }
    .infor-body{
      padding-bottom: 9px;
    }
    hr {
      margin: 9px 0;
    }
    dl.the-comments dd{
      margin-left: 0;
      padding-top: 10px;
      padding-bottom: 10px;
      border-bottom: 1px dashed #CCC;
    }
    .user-comment p{
      margin:5px 0 0 0;
    }

详情页和评论功能

设计博客章详情页面

/home/shiyanlou/revel_mgo_blog/src/GBlog/app/views/App目录下创建文件BlogInfor.html,输入以下内容:

{{set . "title" "Bloginfor - GBlog" }}
{{set . "home" "active" }}
{{template "header.html" .}}
<div class="content">
    <div class="infor-content">
        <div class="infor-header">
          <h3>Title</h3>
          <div class="subject-infor">
            <span class="label label-success">Author</span>   <span>jov123@163.com</span>  
            <span class="label label-default">Date</span>  2014-04-25 15:04  
            <span class="label label-info">Read</span>  1
          </div>
        </div>
        <div class="infor-body">
          this is the subject
        </div>
    </div>
    <div class="comments">
        <span>Reply</span>
        <hr>
        <dl class="the-comments">
          <dd >
            <span class="label label-default pull-right">#1</span>
            <div class="user-info">
              <a href="#"><strong>omind@163.com</strong></a> ·
              2014-04-25 16:04
            </div>
            <div class="user-comment">
              <p>nice!</p>
            </div>
          </dd>
        </dl>
    </div>
    <div class="comments">
        <div class="comment-form">
          <form action="/docomment" method="post">
            <input type="hidden" name="id" value="{{.blog.Id.Hex}}">
            <input type="hidden" name="rcnt" value="{{.rcnt}}">
            <div class="form-group">
              <label >Email</label>
              {{with $field := field "comment.Email" .}}
              <input type="email" class="form-control" id="{{$field.Id}}" name="{{$field.Name}}"  placeholder="Your email" required value="{{if $field.Flash}}{{$field.Flash}}{{else}}{{$field.Value}}{{end}}">
              <span class="help-inline erro">{{$field.Error}}</span>
              {{end}}
            </div>
            <div class="form-group">
              <label >Comment</label>
              {{with $field := field "comment.Content" .}}
              <textarea class="form-control" id="{{$field.Id}}" name="{{$field.Name}}" rows="6" placeholder="Enter the comment" required >{{if $field.Flash}}{{$field.Flash}}{{else}}{{$field.Value}}{{end}}</textarea>
              {{end}}
            </div>
            <div class="form-group">
              <button type="submit" class="btn btn-success">Submit</button>
            </div>
          </form>
        </div>
    </div>
</div>
{{template "footer.html" .}}

接着添加相应的的controller和routes,编辑文件/home/shiyanlou/revel_mgo_blog/src/GBlog/app/controllers/app.go 添加以下方法:

func (c App) BlogInfor() revel.Result {
  return c.Render()
}

/home/shiyanlou/revel_mgo_blog/src/GBlog/conf/routes中加入以下路由:

GET     /bloginfor                              App.BlogInfor

现在访问http://localhost:9000/bloginfor访问看看,效果如下:

此处输入图片的描述

实现博客详情页

/home/shiyanlou/revel_mgo_blog/src/GBlog/app/views/App/Index.html页面中,有以下代码:

<a href="/bloginfor/{{$blog.Id.Hex}}/{{$blog.ReadCnt}}" class="cell-subject-title" title="{{$blog.Title}}"><strang>{{$blog.GetShortTitle }}</strang></a>

其中,博客文章的链接是通过/bloginfor/{{$blog.Id.Hex}}/{{$blog.ReadCnt}}方式生成的,我们传递了Blog对象的id和阅读次数, 用于增加文章的阅读数。

接着调整 /home/shiyanlou/revel_mgo_blog/src/GBlog/conf/routes 中路由条目App.BlogInfor为以下内容,以增加参数配置:

 GET     /bloginfor/:id/:rcnt                    App.BlogInfor

同时也要调整/home/shiyanlou/revel_mgo_blog/src/GBlog/app/controllers/app.go中的BlogInfor方法,以接收参数,调整为如下:

func (c App) BlogInfor(id string,rcnt int) revel.Result {
  dao, err := models.NewDao()
  if err != nil {
    c.Response.Status = 500
    return c.RenderError(err)
  }
  defer dao.Close()
  blog := dao.FindBlogById(id)
  if(blog.ReadCnt==rcnt){
    blog.ReadCnt = rcnt+1
    dao.UpdateBlogById(id,blog)
  }
  return c.Render(blog, rcnt)
}

以上方法中,我们首先根据Blog ID在数据库中查找文章,找到后判断参数rcnt是否和数据库中几率的阅读数一致,如果一致的话,则增加阅读数一次。同时也看到,我们使用了两个新的方法FindBlogByIdUpdateBlogById,编辑/home/shiyanlou/revel_mgo_blog/src/GBlog/app/models/blog.go增加下面两个方法:

  func (dao *Dao) FindBlogById(id string) *Blog{
    blogCollection := dao.session.DB(DbName).C(BlogCollection)
    blog := new(Blog)
    query := blogCollection.Find(bson.M{"id": bson.ObjectIdHex(id)})
    query.One(blog)
    return blog
  }

  func (dao *Dao) UpdateBlogById(id string,blog *Blog) {
    blogCollection := dao.session.DB(DbName).C(BlogCollection)
    err := blogCollection.Update(bson.M{"id": bson.ObjectIdHex(id)}, blog)
    if err!=nil{
      revel.WARN.Printf("Unable to update blog: %v error %v", blog, err)
    }
  }

同时需要再次编辑 /home/shiyanlou/revel_mgo_blog/src/GBlog/app/views/App/BlogInfor.html文件,替换成下面的内容:

 {{set . "title" "Bloginfor - GBlog" }}
    {{set . "home" "active" }}
    {{template "header.html" .}}
    <div class="content">
        {{if .blog}}
        <div class="infor-content">
            <div class="infor-header">
              <h3>{{.blog.Title}}</h3>
              <div class="subject-infor">
                <span class="label label-success">Author</span>   <span>{{.blog.Email}}</span>  
                <span class="label label-default">Date</span>  {{.blog.CDate.Format "2006-01-02 15:04"}}  
                <span class="label label-info">Read</span>  {{.blog.ReadCnt}}
              </div>
            </div>
            <div class="infor-body">
              {{.blog.Subject}}
            </div>
        </div>
        <div class="comments">
            <span>Reply</span>
            <hr>
            <dl class="the-comments">
              <dd >
                <span class="label label-default pull-right">#1</span>
                <div class="user-info">
                  <a href="#"><strong>omind@163.com</strong></a> ·
                  2014-04-25 16:04
                </div>
                <div class="user-comment">
                  <p>nice!</p>
                </div>
              </dd>
            </dl>
        </div>
        <div class="comments">
            <div class="comment-form">
              <form action="/docomment" method="post">
                <input type="hidden" name="id" value="{{.blog.Id.Hex}}">
                <input type="hidden" name="rcnt" value="{{.rcnt}}">
                <div class="form-group">
                  <label >Email</label>
                  {{with $field := field "comment.Email" .}}
                  <input type="email" class="form-control" id="{{$field.Id}}" name="{{$field.Name}}"  placeholder="Your email" required value="{{if $field.Flash}}{{$field.Flash}}{{else}}{{$field.Value}}{{end}}">
                  <span class="help-inline erro">{{$field.Error}}</span>
                  {{end}}
                </div>
                <div class="form-group">
                  <label >Comment</label>
                  {{with $field := field "comment.Content" .}}
                  <textarea class="form-control" id="{{$field.Id}}" name="{{$field.Name}}" rows="6" placeholder="Enter the comment" required >{{if $field.Flash}}{{$field.Flash}}{{else}}{{$field.Value}}{{end}}</textarea>
                  {{end}}
                </div>
                <div class="form-group">
                  <button type="submit" class="btn btn-success">Submit</button>
                </div>
              </form>
            </div>
        </div>
        {{end}}
    </div>
    {{template "footer.html" .}}

现在我们可以在首页点击某一个博客文章标题,现在能跳转到相应的文章详情页面了。

实现评论功能

评论肯定也是需要存储到数据库中,这就需要我们实现model。在/home/shiyanlou/revel_mgo_blog/src/GBlog/app/models目录中,创建文件comment.go,输入以下内容:

package models

import (
  "github.com/revel/revel"
  "gopkg.in/mgo.v2/bson"
  "time"
)

type Comment struct{
  BlogId bson.ObjectId 
  Email string
  CDate time.Time
  Content string
}

func (comment *Comment) Validate(v *revel.Validation) {
  v.Check(comment.Email,
    revel.Required{},
    revel.MaxSize{50},
  )
  v.Email(comment.Email)
  v.Check(comment.Content,
    revel.Required{},
    revel.MinSize{1},
    revel.MaxSize{1000},
  )
}

// 插入评论
func (dao *Dao) InsertComment(comment *Comment) error {
  commCollection := dao.session.DB(DbName).C(CommentCollection)
  //set the time
  comment.CDate = time.Now();
  err := commCollection.Insert(comment)
  if err != nil {
    revel.WARN.Printf("Unable to save Comment: %v error %v", comment, err)
  }
  return err
}

// 查找评论
func (dao *Dao) FindCommentsByBlogId(id bson.ObjectId) []Comment{
  commCollection := dao.session.DB(DbName).C(CommentCollection)
  comms := []Comment{}
  query := commCollection.Find(bson.M{"blogid":id}).Sort("CDate")
  query.All(&comms)
  return comms
}

以上代码和blog.go代码非常相似,定义了Comment结构体用于存储评论,以及一系列查找编辑方法。

我们要在BlogInfor.html页面里提交评论,肯定需要一个方法来接收这个评论的,下面就让我们来实现它,在/home/shiyanlou/revel_mgo_blog/src/GBlog/app/controllers目录中创建文件wcomment.go,输入以下内容:

 package controllers

  import (
    "github.com/revel/revel"
    "GBlog/app/models"
    "strings"
  )
  type WComment struct {
    App
  }
  func (c WComment) Docomment(id string,rcnt int,comment *models.Comment) revel.Result {
    if len(id)==0{
      return c.Redirect(App.Index)
    }
    dao, err := models.NewDao()
    if err != nil {
      c.Response.Status = 500
      return c.Redirect(App.Index)
    }
    defer dao.Close()
    blog := dao.FindBlogById(id)
    if blog==nil {
      return c.Redirect(App.Index)
    }
    comment.BlogId = blog.Id
    comment.Content = strings.TrimSpace(comment.Content)
    comment.Email = strings.TrimSpace(comment.Email)
    comment.Validate(c.Validation)
    if c.Validation.HasErrors() {
      c.Validation.Keep()
      c.FlashParams()
      c.Flash.Error("Errs:The email and the content should not be null,or the maxsize of email is 50.")
      return c.Redirect("/bloginfor/%s/%d",id,rcnt)
    }
    err = dao.InsertComment(comment)
    if err!=nil {
      c.Response.Status = 500
      return c.RenderError(err)
    }
    blog.CommentCnt++
    dao.UpdateBlogById(id,blog)
    return c.Redirect("/bloginfor/%s/%d",id,rcnt)
  }

以上代码中,我们首先根据参数id查找Blog对象,然后插入相应的评论。同时我们需要添加路由,编辑/home/shiyanlou/revel_mgo_blog/src/GBlog/conf/routes加入以下路由:

POST    /docomment                                WComment.Docomment

现在为止我们可以提交评论啦,但是我们还需要在详情页面中显示评论,为了显示命令,我们需要博客的评论传递到模板中,同时在模板中遍历显示评论。下面让我们来实现。

手下在/home/shiyanlou/revel_mgo_blog/src/GBlog/app/controllers/app.go里的BlogInfor方法里,在return关键字之前添加以下代码:

  comments := dao.FindCommentsByBlogId(blog.Id);
if len(comments)==0&&blog.CommentCnt!=0{
    blog.CommentCnt=0;
    dao.UpdateBlogById(id,blog)
}else if len(comments)!=blog.CommentCnt{
    blog.CommentCnt=len(comments);
    dao.UpdateBlogById(id,blog)
}

同时将return语句修改为:

return c.Render(blog,rcnt,comments)

同时在模板中遍历评论,编辑/home/shiyanlou/revel_mgo_blog/src/GBlog/app/views/App/BlogInfor.html,将其中的块:

 <div class="comments">
    <span>Reply</span>
    <hr>
    <dl class="the-comments">
      <dd >
        <span class="label label-default pull-right">#1</span>
        <div class="user-info">
          <a href="#"><strong>omind@163.com</strong></a> ·
          2014-04-25 16:04
        </div>
        <div class="user-comment">
          <p>nice!</p>
        </div>
      </dd>
    </dl>
</div>

修改为:

{{if .comments}}
<div class="comments">
    <span>Reply</span>
    <hr>
    <dl class="the-comments">
       {{range $index,$comment := .comments}}
      <dd >
        <span class="label label-default pull-right">#{{pls $index 1}}</span>
        <div class="user-info">
          <a href="#"><strong>{{$comment.Email}}</strong></a> ·
          {{$comment.CDate.Format "2006-01-02 15:04" }}
        </div>
        <div class="user-comment">
          <p>{{$comment.Content}}</p>
        </div>
      </dd>
      {{end}}
    </dl>
</div>
{{end}}

在上面的代码中,我们使用到了{{pls $index }},其中pls,我们定义的一个模板函数, 用于显示评论的楼层。下面在 /home/shiyanlou/revel_mgo_blog/src/GBlog/app/init.go中的 init方法里添加如下代码:

revel.TemplateFuncs["pls"] = func(a, b int) int { return a + b }

再次刷新页面,你就能看到评论功能工作正常啦,效果如下:

此处输入图片的描述

留言功能

设计留言板页面

/home/shiyanlou/revel_mgo_blog/src/GBlog/app/views/App目录中创建文件Message.html,输入以下内容:

  {{set . "title" "Message - GBlog"}}
  {{set . "mess" "active" }}
  {{template "header.html" .}}
  <div class="content">
      <div class="comment-nav">
         <div class="comment-title">
           Message Board
           <span style="float:right" title="Total messages">[100]</span>
         </div>
         <div class="comment-cell">
           <div class="comment-inputbox">
              <form action="/putmessage" method="post" >
                    <ul class="comment-input-infor">
                      {{with $field := field "message.Email" .}}
                      <li>
                        EMAIL
                        <input type="email"  id="{{$field.Id}}" name="{{$field.Name}}" class="form-control " required value="{{if $field.Error}}{{$field.Error}}{{else}}{{$field.Value}}{{end}}"/>
                      </li>
                       {{end}}
                      <li>
                        QQ
                        {{with $field := field "message.QQ" .}}
                        <input type="text"  id="{{$field.Id}}" name="{{$field.Name}}" class="form-control" value="{{if $field.Error}}{{$field.Error}}{{else}}{{$field.Value}}{{end}}" />
                        {{end}}
                      </li>
                      <li>
                        Personal home page
                        {{with $field := field "message.Url" .}}
                        <input type="text"  id="{{$field.Id}}" name="{{$field.Name}}" class="form-control" placeholder="Don't with http://  " value="{{if $field.Error}}{{$field.Error}}{{else}}{{$field.Value}}{{end}}"/>
                        {{end}}
                      </li>
                    </ul>
                    <div class="comment-input-text">
                      MESSAGE
                      <div>
                        {{with $field := field "message.Content" .}}
                        <textarea class="form-control ctextarea" id="{{$field.Id}}" name="{{$field.Name}}" required>{{if $field.Error}}{{$field.Error}}{{else}}{{$field.Value}}{{end}}</textarea>
                        {{end}}
                      </div>
                    </div>
                    <button type="submit" class="btn btn-success comment-input-text-btn">SUBMIT</button>
              </form>
           </div>
         </div>
         <div class="comment-cell">
           <pre ><code><span class="func-color">func</span><span class="func-name"> UserMessage</span><span class="pln">() </span><span class="pun">{</span><span class="pln">
      </span><span class="func-color">var</span><span class="pun"> </span><span class="pln">email </span><span class="func-type">string </span><span class="pun">=</span><span class="pln"> </span><span class="func-str">"jov123@163.com"</span><span class="pun">;</span><span class="pln-w">
      </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln">url </span><span class="pln">=</span><span class="pln-w"> </span><a href="http://jov." class="func-str" target="_blank">http://jov.</a><span class="pln-w">;</span><span class="pln">
      </span><span class="lit">Date </span><span class="func-color">:=</span><span class="pln"> </span><span class="func-str">"2014-04-15 12:50"</span><span class="pun">;</span><span class="pln">
      </span><span class="func-color">var </span><span class="lit">Message</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="func-str">"nice!"</span><span class="pln">;
  </span><span class="pun">}</span><span class="pln">
  </code></pre>
         </div>
          <div class="comment-cell">
           <pre style="background:#2d2d2d;"><code><span class="func-color">func</span><span class="func-name"> UserMessage</span><span class="pln-w">() </span><span class="pln-w">{</span><span class="pln-w">
      </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln-w">email </span><span class="func-type">string </span><span class="pln-w">=</span><span class="pln-w"> </span><span class="func-str">"jov123@163.com"</span><span class="pln-w">;</span><span class="pln-w">
      </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln-w">url </span><span class="pln-w">=</span><span class="pln-w"> </span><a href="http://jov." class="func-str" target="_blank">http://jov.</a><span class="pln-w">;</span><span class="pln-w">
      </span><span class="pln-w">Date </span><span class="func-color">:=</span><span class="pln-w"> </span><span class="func-str">"2014-04-15 12:50"</span><span class="pln-w">;</span><span class="pln-w">
      </span><span class="func-color">var </span><span class="pln-w">Message</span><span class="pln-w"> </span><span class="pln-w">=</span><span class="pln-w"> </span><span class="func-str">"nice!"</span><span class="pln-w">;
  </span><span class="pln-w">}</span><span class="pln-w">
  </code></pre>
         </div>
    </div>
  </div>
  {{template "footer.html" .}}

接着添加相应的的controller和路由,编辑 /home/shiyanlou/revel_mgo_blog/src/GBlog/conf/routes文件,添加以下路由:

GET     /message                                App.Message

/home/shiyanlou/revel_mgo_blog/src/GBlog/app/controllers/app.go里添加方法:

func (c App) Message() revel.Result {
  return c.Render()
}

然后点击菜单栏的留言就可以看到效果了。现在只是一个展示页面,下面让我们真正实现它。

实现留言板功能

类似于评论功能的实现,我们需要依次实现model,controller等。首先在 `下新建文件message.go`,输入以下内容:

package models
  import (
    "github.com/revel/revel"
    "gopkg.in/mgo.v2/bson"
    "time"
  )
  type Message struct{
    Email string
    QQ string
    Url string
    CDate time.Time
    Content string
  }
  func (message *Message) Validate(v *revel.Validation) {
    v.Check(message.Email,
      revel.Required{},
      revel.MaxSize{50},
    )
    v.Email(message.Email)
    v.Check(message.QQ,
      revel.MaxSize{20},
    )
    v.Check(message.Url,
      revel.MaxSize{200},
    )
    v.Check(message.Content,
      revel.Required{},
      revel.MinSize{1},
      revel.MaxSize{1000},
    )
  }
  func (dao *Dao) InsertMessage(message *Message) error {
    messCollection := dao.session.DB(DbName).C(MessageCollection)
    //set the time
    message.CDate = time.Now();
    err := messCollection.Insert(message)
    if err != nil {
      revel.WARN.Printf("Unable to save Message: %v error %v", message, err)
    }
    return err
  }
  func (dao *Dao) FindAllMessages() []Message{
    messCollection := dao.session.DB(DbName).C(MessageCollection)
    mess := []Message{}
    query := messCollection.Find(bson.M{}).Sort("-cdate")
    query.All(&mess)
    return mess
  }

接着添加相应的controller,在`目录下新建wmessage.go`,输入以下内容:

package controllers

  import (
    "github.com/revel/revel"
    "GBlog/app/models"
    "strings"
    "fmt"
  )
  type WMessage struct {
    App
  }
  func (c WMessage) Putup(message *models.Message) revel.Result {
    message.Email = strings.TrimSpace(message.Email);
    message.Url = strings.TrimSpace(message.Url);
    message.Content = strings.TrimSpace(message.Content);
    message.QQ = strings.TrimSpace(message.QQ);
    message.Validate(c.Validation)
    fmt.Println(c.Validation)
    if c.Validation.HasErrors() {
      c.Validation.Keep()
      c.FlashParams()
      c.Flash.Error("Errs:The email and the content should not be null,or the maxsize of email is 50.")
      return c.Redirect(App.Message)
    }
    dao, err := models.NewDao()
    if err != nil {
      c.Response.Status = 500
      return c.RenderError(err)
    }
    defer dao.Close()
    err = dao.InsertMessage(message)
    if(err!=nil){
      c.Response.Status = 500
      return c.RenderError(err)
    }
    return c.Redirect(App.Message)
  }

然后再/home/shiyanlou/revel_mgo_blog/src/GBlog/conf/routes中添加以下路由:

POST   /putmessage                           WMessage.Putup

经过以上步骤,我们发布留言的功能就实现了,但是怎么显示留言呢?这就需要修改之前设计的Mesage()方法和Message.html页面了。

首先修改/home/shiyanlou/revel_mgo_blog/src/GBlog/app/controllers/app.go中的Mesasge()方法为以下内容:

  func (c App) Message() revel.Result {
    dao, err := models.NewDao()
    if err != nil {
      c.Response.Status = 500
      return c.RenderError(err)
    }
    defer dao.Close()
    //dao := models.NewDao(c.MongoSession)
    messages := dao.FindAllMessages()
    return c.Render(messages)
  }

接着调整页面/home/shiyanlou/revel_mgo_blog/src/GBlog/app/views/App/Message.html为以下内容:

    {{set . "title" "Message - GBlog"}}
    {{set . "mess" "active" }}
    {{template "header.html" .}}
    <div class="content">
        <div class="comment-nav">
           <div class="comment-title">
             Message Board
             <span style="float:right" title="Total messages">[{{len .messages}}]</span>
           </div>
           <div class="comment-cell">
             <div class="comment-inputbox">
                <form action="/putmessage" method="post" >
                      <ul class="comment-input-infor">
                        {{with $field := field "message.Email" .}}
                        <li>
                          EMAIL
                          <input type="email"  id="{{$field.Id}}" name="{{$field.Name}}" class="form-control " required value="{{if $field.Error}}{{$field.Error}}{{else}}{{$field.Value}}{{end}}"/>
                        </li>
                         {{end}}
                        <li>
                          QQ
                          {{with $field := field "message.QQ" .}}
                          <input type="text"  id="{{$field.Id}}" name="{{$field.Name}}" class="form-control" value="{{if $field.Error}}{{$field.Error}}{{else}}{{$field.Value}}{{end}}" />
                          {{end}}
                        </li>
                        <li>
                          Personal home page
                          {{with $field := field "message.Url" .}}
                          <input type="text"  id="{{$field.Id}}" name="{{$field.Name}}" class="form-control" placeholder="Don't with http://  " value="{{if $field.Error}}{{$field.Error}}{{else}}{{$field.Value}}{{end}}"/>
                          {{end}}
                        </li>
                      </ul>
                      <div class="comment-input-text">
                        MESSAGE
                        <div>
                          {{with $field := field "message.Content" .}}
                          <textarea class="form-control ctextarea" id="{{$field.Id}}" name="{{$field.Name}}" required>{{if $field.Error}}{{$field.Error}}{{else}}{{$field.Value}}{{end}}</textarea>
                          {{end}}
                        </div>
                      </div>
                      <button type="submit" class="btn btn-success comment-input-text-btn">SUBMIT</button>
                </form>
             </div>
           </div>
           {{if .messages}}
           {{range $index,$message:=.messages}}
           {{if mo $index 2}}
           <div class="comment-cell">
             <pre ><code><span class="func-color">func</span><span class="func-name"> UserMessage</span><span class="pln">() </span><span class="pln">{</span><span class="pln-w">
        </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln">email </span><span class="func-type">string </span><span class="pln">=</span><span class="pln"> </span><span class="func-str">"{{$message.Email}}"</span><span class="pln">;</span>{{if $message.QQ}}<span class="pln-w">
        </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln">QQ </span><span class="pln">=</span><span class="pln-w"> </span><span class="func-str" >{{$message.QQ}}</span><span class="pln">;</span>{{end}}{{if $message.Url}}<span class="pln-w">
        </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln">url </span><span class="pln">=</span><span class="pln-w"> </span><a href="http://{{$message.Url}}" class="func-str" target="_blank">http://{{$message.Url}}</a><span class="pln">;</span>{{end}}<span class="pln-w">
        </span><span class="pln">Date </span><span class="func-color">:=</span><span class="pln-w"> </span><span class="func-str">"{{$message.CDate.Format "2006-01-02 15:04"}}"</span><span class="pln">;</span><span class="pln-w">
        </span><span class="func-color">var </span><span class="pln">Message</span><span class="pln-w"> </span><span class="pln">=</span><span class="pln-w"> </span><span class="func-str">"{{$message.Content}}"</span><span class="pln">;
    </span><span class="pln">}</span><span class="pln-w">
    </code></pre>
           </div>
           {{else}}
           <div class="comment-cell">
             <pre style="background:#2d2d2d;"><code><span class="func-color">func</span><span class="func-name"> UserMessage</span><span class="pln-w">() </span><span class="pln-w">{</span><span class="pln-w">
        </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln-w">email </span><span class="func-type">string </span><span class="pln-w">=</span><span class="pln-w"> </span><span class="func-str">"{{$message.Email}}"</span><span class="pln-w">;</span>{{if $message.QQ}}<span class="pln-w">
        </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln-w">QQ </span><span class="pln-w">=</span><span class="pln-w"> </span><span class="func-str" >{{$message.QQ}}</span><span class="pln-w">;</span>{{end}}{{if $message.Url}}<span class="pln-w">
        </span><span class="func-color">var</span><span class="pln-w"> </span><span class="pln-w">url </span><span class="pln-w">=</span><span class="pln-w"> </span><a href="http://{{$message.Url}}" class="func-str" target="_blank">http://{{$message.Url}}</a><span class="pln-w">;</span>{{end}}<span class="pln-w">
        </span><span class="pln-w">Date </span><span class="func-color">:=</span><span class="pln-w"> </span><span class="func-str">"{{$message.CDate.Format "2006-01-02 15:04"}}"</span><span class="pln-w">;</span><span class="pln-w">
        </span><span class="func-color">var </span><span class="pln-w">Message</span><span class="pln-w"> </span><span class="pln-w">=</span><span class="pln-w"> </span><span class="func-str">"{{$message.Content}}"</span><span class="pln-w">;
    </span><span class="pln-w">}</span><span class="pln-w">
    </code></pre>
           </div>
           {{end}}
           {{end}}
           {{end}}
      </div>
    </div>
    {{template "footer.html" .}}

Message.html中,我们用到了{{if mo $index 2}}这段代码,其中mo我们自定义的模板函数,需要在 /home/shiyanlou/revel_mgo_blog/src/GBlog/app/init.goinit方法中添加以下代码后才能使用:

revel.TemplateFuncs["mo"] = func(a, b int) bool { return a%b==0 }

到这里整个留言板功能就完成啦,效果如下:

此处输入图片的描述

下一节,我们将实现归档功能。

动手实践是学习 IT 技术最有效的方式! 开始实验

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约