这是应用的Example。基本代码在:golang-code / handler / handler.go(主题应该出现一个ID!)
我试图在Google Appengine上的Golang中构建一个小博客系统,并使用Mustache作为模板引擎。
所以,我有一个结构:
type Blogposts struct {
PostTitle string
PostPreview string
Content string
Creator string
Date time.Time
}
数据通过
传递给GAE datastore.Put(c, datastore.NewIncompleteKey(c, "Blogposts", nil), &blogposts)
因此,GAE自动分配一个intID(int64)。 现在我试图获得最新的博客
// Get the latest blogposts
c := appengine.NewContext(r)
q := datastore.NewQuery("Blogposts").Order("-Date").Limit(10)
var blogposts []Blogposts
_, err := q.GetAll(c, &blogposts)
直到所有事情都正常,但当我尝试访问intID(或stringID,无论如何)时,我无法访问: - (
<h3><a href="/blog/read/{{{intID}}}">{{{PostTitle}}}</a></h3>
(PostTitle有效,intID没有,我已经尝试了数千件事,没有用:-()
有人有想法吗?这太棒了!
编辑: 我用胡子。
在我使用的代码中:
x["Blogposts"] = blogposts
data := mustache.RenderFile("templates/about.mustache", x)
sendData(w, data) // Equivalent to fmt.Fprintf
然后可以使用{{{Content}}}或{{{PostTitle}}}等在.mustache模板中访问数据。
答案 0 :(得分:15)
正如hyperslug所指出的,实体的id字段在键上,而不是它被读入的结构。
另一种方法是在结构中添加一个id字段,并将数据存储区告诉ignore it,例如:
type Blogposts struct {
PostTitle string
PostPreview string
Content string
Creator string
Date time.Time
Id int64 `datastore:"-"`
}
然后,您可以在调用GetAll()之后手动填充Id字段
keys, err := q.GetAll(c, &blogposts)
if err != nil {
// handle the error
return
}
for i, key := range keys {
blogposts[i].Id = key.IntID()
}
这样做的好处是不会引入额外的类型。
答案 1 :(得分:7)
intID
是Key的内部属性而不是struct,可以通过getter访问:
id := key.IntID()
GetAll
会返回您未使用的[]*Key
:
_, err := q.GetAll(c, &blogposts)
解决此问题的一种方法是创建一个包含帖子和密钥信息的viewmodel结构(未经测试,但这是它的要点):
//... handler code ...
keys, err := q.GetAll(c, &blogposts)
if err != nil {
http.Error(w, "Problem fetching posts.", http.StatusInternalServerError)
return
}
models := make([]BlogPostVM, len(blogposts))
for i := 0; i < len(blogposts); i++ {
models[i].Id = keys[i].IntID()
models[i].Title = blogposts[i].Title
models[i].Content = blogposts[i].Content
}
//... render with mustache ...
}
type BlogPostVM struct {
Id int
Title string
Content string
}
答案 2 :(得分:2)
我知道这个问题已有几年了,但以下文章在这方面对我非常有帮助:Golang basics with Google Datastore。
在文章中,作者提供了一个很好的示例,说明如何运行通过其ID获取实体的查询...
func GetCategory(c appengine.Context, id int64) (*Category, error) {
var category Category
category.Id = id
k := category.key(c)
err := datastore.Get(c, k, &category)
if err != nil {
return nil, err
}
category.Id = k.IntID()
return &category, nil
}
...以及获取具有关联ID的实体列表/集合:
func GetCategories(c appengine.Context) ([]Category, error) {
q := datastore.NewQuery("Category").Order("Name")
var categories []Category
keys, err := q.GetAll(c, &categories)
if err != nil {
return nil, err
}
// you'll see this a lot because instances
// do not have this by default
for i := 0; i < len(categories); i++ {
categories[i].Id = keys[i].IntID()
}
return categories, nil
}
上面的代码段非常接近@koz的有用答案。
答案 3 :(得分:0)
AFAICS,Blogposts
结构没有字段intID
,但它有一个字段PostTitle
。我想这可能是为什么前者没有,后者确实被渲染的原因,尽管我从未使用过胡子......