【Go web开发之revel+mgo】第3章 Blog的首页与投稿实现

演示地址   http://gblog-revel.herokuapp.com/

1.实现投稿功能

我们先在app下建一个models文件夹(放的主要是我们的db models),在models里先建一个dao.go(恩,名字起的有点类似orm的概念,其实我们是可以使用orm框架来做的)内容:
package models
import (
	"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 models
import (
	"github.com/revel/revel"
	"labix.org/v2/mgo/bson"
	"time"
)
type Blog struct {
	Id bson.ObjectId 
	Email string
	CDate time.Time
	Title string
	ShortTitle string
	Subject string
	ShortSubject string
	CommentCnt int
	ReadCnt int
	Year 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 time
	blog.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 controllers

import (
	"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 = 500
		return c.RenderError(err)
	}
	defer dao.Close()
	err = dao.CreateBlog(blog)
	if(err!=nil){
		c.Response.Status = 500
		return 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 controllers

import (
	"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 = 500
		return 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这两个字段去了。
好了,完成了。

来看看效果:



恩就这么多了。


交流QQ:158325682

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值