英文:
Golang GAE - intID in struct for mustache
问题
这是一个应用程序的示例。关键代码在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)。
现在我尝试获取最新的博客文章
// 获取最新的博客文章
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不行,我尝试了很多方法,都没有成功 :-()
有人有想法吗?这将非常棒!
编辑:
我使用mustache。
在代码中,我使用:
x["Blogposts"] = blogposts
data := mustache.RenderFile("templates/about.mustache", x)
sendData(w, data) // 等同于 fmt.Fprintf
然后可以在.mustache模板中通过{{{Content}}}或{{{PostTitle}}}等方式访问数据。
英文:
Here is an Example of the app. The essential code is in: golang-code/handler/handler.go (After the subject should appear an ID!)
Im trying to build a little blog system in Golang on Google Appengine and use Mustache as template engine.
So, i have a struct:
type Blogposts struct {
PostTitle string
PostPreview string
Content string
Creator string
Date time.Time
}
The data is passed to GAE via
datastore.Put(c, datastore.NewIncompleteKey(c, "Blogposts", nil), &blogposts)
So, GAE assigns automatically a intID (int64).
Now I tried to get the latest blogposts
// Get the latest blogposts
c := appengine.NewContext(r)
q := datastore.NewQuery("Blogposts").Order("-Date").Limit(10)
var blogposts []Blogposts
_, err := q.GetAll(c, &blogposts)
Until there all things works fine, but when I try to access intID (or stringID, whatever) I dont have access to this
<h3><a href="/blog/read/{{{intID}}}">{{{PostTitle}}}</a></h3>
(PostTitle works, intID not, i've tried thousand of things, nothing worked )
Anyone an idea? This would be great!
Edit:
I use mustache.
In the code I use:
x["Blogposts"] = blogposts
data := mustache.RenderFile("templates/about.mustache", x)
sendData(w, data) // Equivalent to fmt.Fprintf
And then the data can be accessed in the .mustache template with {{{Content}}} or {{{PostTitle}}} etc.
答案1
得分: 15
正如hyperslug所指出的,实体的id字段位于键上,而不是它被读入的结构体上。
另一种解决方法是在结构体中添加一个id字段,并告诉数据存储忽略它,例如:
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 {
// 处理错误
return
}
for i, key := range keys {
blogposts[i].Id = key.IntID()
}
这样做的好处是不会引入额外的类型。
英文:
As hyperslug pointed out, the id field of an entity is on the key, not the struct it gets read into.
Another way around this is to add an id field to your struct and tell datastore to ignore it, eg:
type Blogposts struct {
PostTitle string
PostPreview string
Content string
Creator string
Date time.Time
Id int64 `datastore:"-"`
}
You can then populate the Id field manually after a call to GetAll() like so
keys, err := q.GetAll(c, &blogposts)
if err != nil {
// handle the error
return
}
for i, key := range keys {
blogposts[i].Id = key.IntID()
}
This has the benefit of not introducing an extra type.
答案2
得分: 7
intID
是Key的一个内部属性,而不是结构体,可以通过getter方法访问:
id := key.IntID()
GetAll
返回[]*Key
,你没有使用它:
_, err := q.GetAll(c, &blogposts)
解决这个问题的一种方法是创建一个视图模型结构体,其中包含您的帖子和键信息(未经测试,但这是要点):
//... 处理程序代码 ...
keys, err := q.GetAll(c, &blogposts)
if err != nil {
http.Error(w, "获取帖子时出现问题。", 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
}
//... 使用mustache渲染 ...
}
type BlogPostVM struct {
Id int
Title string
Content string
}
英文:
intID
is an internal property of a Key not the struct, and is accessible through a getter:
id := key.IntID()
GetAll
returns []*Key
, which you're not using:
_, err := q.GetAll(c, &blogposts)
One way to get around this is to create a viewmodel struct that has both your post and key info (untested, but this is the gist of it):
//... 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
}
答案3
得分: 2
我知道这个问题已经有几年了,但是下面的文章对我在这方面非常有帮助:使用Google Datastore的Golang基础知识。
在这篇文章中,作者提供了一个很好的例子,展示了如何通过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
}
// 你会经常看到这个,因为实例默认没有这个
for i := 0; i < len(categories); i++ {
categories[i].Id = keys[i].IntID()
}
return categories, nil
}
上面的代码片段与@koz提供的有用答案非常接近。
英文:
I know this question is a couple years old, but the following article was very helpful to me in this regard: Golang basics with Google Datastore.
In the article, the author provides a nice example of how you can run a query that gets an entity by its 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
}
...as well as getting a list/collection of entities with their associated 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
}
The snippet above is very close to the helpful answer by @koz.
答案4
得分: 0
AFAICS,Blogposts
结构体没有intID
字段,但它有一个PostTitle
字段。我猜这可能是前者没有被渲染而后者被渲染的原因,尽管我从未使用过Mustache...
英文:
AFAICS, the Blogposts
struct has no field intID
, but it has a field PostTitle
. I guess that could be the reason why the former doesn't and the later does get rendered, though I've never used Mustache...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论