這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
示範地址 http://gblog-revel.herokuapp.com/
1.實現投稿功能
我們先在app下建一個models檔案夾(放的主要是我們的db models),在models裡先建一個dao.go(恩,名字起的有點類似orm的概念,其實我們是可以使用orm架構來做的)內容:
package modelsimport ("labix.org/v2/mgo")const (DbName = "ominds"BlogCollection = "blogs"CommentCollection = "gb_comments"MessageCollection = "gb_messages"HistoryCollection = "gb_historys"EmailCollection = "gb_emails"BaseYear = 2014)type Dao struct {session *mgo.Session}func NewDao() (*Dao, error){//session, err := mgo.Dial("mongodb://omind:jov.omind@widmore.mongohq.com:10000/ominds")session, err := mgo.Dial("localhost")if err != nil {return nil, err}return &Dao{session}, nil}func (d *Dao) Close() {d.session.Close()}
首先是package,這個是包名,沒什麼好說的,然後const裡面的常量,DbName是我的資料庫名詞(至於為什麼叫ominds,這是我一前做nodejs的一個db就直接拿來用了),其中的很多Collection是我們的表名。看一下,NewDao裡面的東西:
session, err := mgo.Dial("localhost")
這是我們要使用本機資料庫的意思(這個string其實可以放到app.conf裡面配置的,但不知道為什麼,總是擷取不到值,無奈,我只能改成這樣了),看到其中的被注釋的一行了嗎,那是我在mongohq(如果你不知道什麼是mongohq,請到我的blog中看一下nodejs開發的最後一章)申請的db的uri,如果你用的是雲db,你也可以這麼做。
好了,db連結已經建好了。我們再在models下建立一個blog.go檔案:
package modelsimport ("github.com/revel/revel""labix.org/v2/mgo/bson""time")type Blog struct {Id bson.ObjectId Email stringCDate time.TimeTitle stringShortTitle stringSubject stringShortSubject stringCommentCnt intReadCnt intYear int }func (blog *Blog) Validate(v *revel.Validation) {v.Check(blog.Title,revel.Required{},revel.MinSize{1},revel.MaxSize{200},)v.Check(blog.Email,revel.Required{},revel.MaxSize{50},)v.Email(blog.Email)v.Check(blog.Subject,revel.Required{},revel.MinSize{1},)}func (dao *Dao) CreateBlog(blog *Blog) error {blogCollection := dao.session.DB(DbName).C(BlogCollection)//set the timeblog.Id = bson.NewObjectId()blog.CDate = time.Now();blog.Year = blog.CDate.Year();_, err := blogCollection.Upsert(bson.M{"_id": blog.Id}, blog)if err != nil {revel.WARN.Printf("Unable to save blog: %v error %v", blog, err)}return err}func (dao *Dao) FindBlogs() []Blog{blogCollection := dao.session.DB(DbName).C(BlogCollection)blogs := []Blog{}query := blogCollection.Find(bson.M{}).Sort("-cdate").Limit(50)query.All(&blogs)return blogs}
其中,Validate方法,我們用了下revel的校正(你也可以自己寫校正哦,後面會說),CreateBlog方法當然就是添加資料了。FindBlogs方法,尋找blog,我們只取了,最近的50條,想看其它的怎麼辦,不是還有歸檔嗎?blog欄位簡單介紹一下,其中Id十一個bson的對象,這個東西該怎麼說呢,因為我們要經常用Id來做操作,這裡把它當作我們的主鍵把,不過mongodb裡面還是會有一個_id的主鍵,關於這塊我自己還有很多疑點,暫時大家先這麼用吧。year這個欄位,主要是用來歸當的,比較挫的辦法。
下面我們在controllers下面建一個wblog.go檔案,內容:
package controllersimport ("github.com/revel/revel""MyTest/app/models""strings""fmt")type WBlog struct {App}func (c WBlog) Putup(blog *models.Blog) revel.Result {blog.Title = strings.TrimSpace(blog.Title);blog.Email = strings.TrimSpace(blog.Email);blog.Subject = strings.TrimSpace(blog.Subject);blog.Validate(c.Validation)if c.Validation.HasErrors() {c.Validation.Keep()c.FlashParams()fmt.Println(c.Validation)return c.Redirect(App.WBlog)}dao, err := models.NewDao()if err != nil {c.Response.Status = 500return c.RenderError(err)}defer dao.Close()err = dao.CreateBlog(blog)if(err!=nil){c.Response.Status = 500return c.RenderError(err)}return c.Redirect(App.Index)}
我們之前的WBlog.html頁面還記得嗎?其中的:
{{with $field := field "blog.Title" .}}
這樣的語句是做什麼 的內,這裡說一下,revel也是有注入機制的,就是向我們的參數blog對象的Title屬性注入內容。
<input type="text" id="{{$field.Id}}" name="{{$field.Name}}" class="form-control" style="width:98%;min-height:28px;" required value="{{if $field.Flash}}{{$field.Flash}}{{else}}{{$field.Value}}{{end}}">
其中的id和name,我們不用管它,你也可以看看它產生的是什麼。value裡面的東西,主要是驗證失敗的情況下返回回來的內容,也是比較又用的東西。
<span class="help-inline erro">{{$field.Error}}</span>
這個是我們這個屬性校正失敗的提示。
另外,在Putup方法裡面如果我們要用自己的校正,那麼 可以這樣做:
c.Validation.MaxSize(blog.Title,256).Message("The title is too long,please checkout it.")
好了,我們在conf/routes下加入我們的route吧。
POST /putblog WBlog.Putup
你現在可以投稿看看是不是可以了哦,校正也是沒問題的。下面我們把首頁來高一搞吧,讓它顯示我們的東西。
首先在controllers/app.go中將裡面替換為:
package controllersimport ("github.com/revel/revel""MyTest/app/models")type App struct {*revel.Controller}func (c App) Index() revel.Result {dao, err := models.NewDao()if err != nil {c.Response.Status = 500return c.RenderError(err)}defer dao.Close()//dao := models.NewDao(c.MongoSession)blogs := dao.FindBlogs()return c.Render(blogs)}func (c App) WBlog() revel.Result {return c.Render()}
恩,Index方法裡面加入了讀取blog的東西。哦,注釋掉的東西,其實是我當初嘗試revmgo留下的。
好下面來修改views/App/Index.html:
{{set . "title" "Home - GBlog" }}{{set . "home" "active" }}{{template "header.html" .}}<div class="content"> {{if .blogs}} {{range $blog := .blogs}} <div class="cell"> <div class="cell-subject"> <div> <a href="/bloginfor/{{$blog.Id.Hex}}/{{$blog.ReadCnt}}" class="cell-subject-title" title="{{$blog.Title}}"><strang>{{$blog.GetShortTitle }}</strang></a> <a href="#" class="comment-num" title="Comments">{{$blog.CommentCnt}}</a> </div> <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="cell-text"> <pre><code>{{$blog.GetShortContent }}</code></pre> </div> </div> {{end}} {{end}}</div>{{template "footer.html" .}}
恩,其中呢GetShortTitle和GetShortContent是兩個新方法,在models/blog.go裡面加入:
func (blog *Blog) GetShortTitle() string{if len(blog.Title)>35 {return blog.Title[:35]}return blog.Title}func (blog *Blog) GetShortContent() string{if len(blog.Subject)>200 {return blog.Subject[:200]}return blog.Subject}
這裡不得不說一下blog中的ShortTitle和ShortSubject欄位了,剛開始使用revel的時候我並不知道,怎麼去截取這個字串,後來,revel中文社區的站長,告訴我可以在model裡面加個方法來處理,而那個時候我已經採用了笨方法,現在呢,交給大家這種方法,所以如果沒什麼必要大家可以把ShortTitle和ShortSubject這兩個欄位去了。好了,完成了。
來看看效果:
恩就這麼多了。
源碼地址:https://github.com/joveth/GBlog
交流QQ:158325682