這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
sorry,各位在開始這一章之前請各位先到,第5章把整個項目的css copy出來,這一章忘了加,本來想在後面加的,但是發現頁面的內容太多了
1.設計評論頁面
上一章我們做了簡單的寫blog和顯示功能,這裡不得不說一下,首先,我們的blog裡面不能加圖片連結這樣的東西,不支援markdown文法。博主比較懶,嘗試找了幾個外掛程式發現不滿意之後就不想嘗試了(其實能找到github編寫wiki的編輯器才是我想要的,有誰知道的告訴我哦),大家可以自己嘗試去找一些自己喜歡的編輯器(雖然revel中文社區的那個已經很不錯了,但是彈出框風格很不喜歡,golang社區的編輯器也很強,但也不是我喜歡的風格,你妹啊,這麼挑剔。。。。),總之,大家可以參考一下,喜歡就用。
在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>回複</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" .}}
在app/controllers/app.go裡面添加我們的處理方法:
func (c App) BlogInfor() revel.Result {return c.Render()}
在conf/routes裡面添加路徑:
GET /bloginfor App.BlogInfor
ok在地址裡面用http://localhost:9000/bloginfor訪問看看,效果:
下面我們來實現它。
2.實現評論功能
首先看一下我們的Index.html裡面的title的連結內容:
/bloginfor/{{$blog.Id.Hex}}/{{$blog.ReadCnt}}
恩,對,我們傳遞了blog的id和閱讀次數,為什麼要傳閱讀次數呢,因為從這個連結點進去的時候我們要把閱讀次數加1,但是如果我們不傳遞,那麼到詳細頁面的時候應該是直接將db裡面的資料增加,這樣就有問題了,我在詳細頁面一直按F5重新整理,發現閱讀次數飛快的增加,這讓我很無奈,怎麼版辦呢,把閱讀次數也傳過來把,至少把原來的一步增加了2步,稍微的緩解一下把,但是仍然不知最好的方法啊,最好的方法是,我們擷取,請求使用者的 IP,做判斷,只能為這個Ip增加一次,這都是後話了。
好了我們修改一下路徑的配置conf/routes:
GET /bloginfor/:id/:rcnt App.BlogInfor
把app/controllers/app.go裡面的BlogInfor方法也加兩個參數:
func (c App) BlogInfor(id string,rcnt int) revel.Result {return c.Render()}
好,我們這次從首頁點擊我們blog的title進去看看,是不是能正常進入詳細頁面。
我這邊是ok的,我們往下進行,首先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 = 500return c.RenderError(err)}defer dao.Close()blog := dao.FindBlogById(id)if(blog.ReadCnt==rcnt){blog.ReadCnt = rcnt+1dao.UpdateBlogById(id,blog)}return c.Render(blog,rcnt)}
我們去找到這個blog,並且把閱讀次數做一下更新,看一下裡面的判斷,我們是把閱讀次數和db中的相比較,只有相等的情況才去更新,這樣確實增加了2步。不過,如果你有時間,你也可以採用另外一種方法,就是把閱讀次數加密(可逆的加密),解密之後再與db中的比較,這樣的話,使用者想要修改加密後的東西並不是一件容易的事件。
那麼我們的model也要有對應的方法,開啟 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)}}
一個是尋找,一個是更新,沒什麼好說的。
開啟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>回複</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" .}}
顯示了 blog資訊。好,點進去看看效果:
ok,我們來做評論。在app/models下建立comment.go 內容:
package modelsimport ("github.com/revel/revel""labix.org/v2/mgo/bson""time")type Comment struct{BlogId bson.ObjectId Email stringCDate time.TimeContent 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 timecomment.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很相似,不用多解釋。有了dao,我們來做邏輯,還是先做提交評論的功能,看下 我們的BlogInfo.html頁面。最後的form表單,裡面的東西跟我們上一章講的差不多。
在app/controllers下面建立wcomment.go,為什麼以w開頭,write嘛,內容:
package controllersimport ("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 = 500return c.Redirect(App.Index)}defer dao.Close()blog := dao.FindBlogById(id)if blog==nil {return c.Redirect(App.Index)}comment.BlogId = blog.Idcomment.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 = 500return c.RenderError(err)}blog.CommentCnt++dao.UpdateBlogById(id,blog)return c.Redirect("/bloginfor/%s/%d",id,rcnt)}
看一下裡面的邏輯,我們先去尋找一下,有沒有這個blog對象,沒有的話,就直接 返回到Index頁面,然後是comment的校正,最後我們的blog的評論次數加1。最後的c.Redirect("/bloginfor/%s/%d",id,rcnt)是讓它再次回到infor頁面的。
好,添加我們的路徑,conf/routes:
POST /docomment WComment.Docomment
你可以試試能不能提交成功了。雖然還看不到什麼結果。下面來顯示我們的評論,在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)
開啟views/App/BlogInfor.html,將其中的塊:
<div class="comments"> <span>回複</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>回複</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 1}}
這個是用來顯示樓層的的東西,這個什麼呢,是我們自訂的模板,這裡不得不感謝revel中文社區的kevin,如果我們直接用$index它是從0開始的,這。。。
好,開啟我們的app/init.go,話說裡面還有很多我也不知到的東西,就不給大家講了,func init() 裡面添加:
revel.TemplateFuncs["pls"] = func(a, b int) int { return a + b }
就是定義了一個簡單的模板方法。
好了嗎。各位,趕快試試期待已久的評論功能把。
nice。你成功了嗎?
源碼地址:https://github.com/joveth/GBlog
交流QQ:158325682