评论和留言功能实现
实验说明
这一节实验中,主要讲解怎么样实现博客的评论和留言功能。
本实验属于实验楼课程《基于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
是否和数据库中几率的阅读数一致,如果一致的话,则增加阅读数一次。同时也看到,我们使用了两个新的方法FindBlogById
和UpdateBlogById
,编辑/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.go
中init
方法中添加以下代码后才能使用:
revel.TemplateFuncs["mo"] = func(a, b int) bool { return a%b==0 }
到这里整个留言板功能就完成啦,效果如下:
下一节,我们将实现归档功能。