Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang GAE - intID in struct for mustache

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.

http://mustache.github.com/

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.

like image 446
Testuser Avatar asked Mar 31 '12 13:03

Testuser


2 Answers

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.

like image 172
koz Avatar answered Nov 15 '22 07:11

koz


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
}
like image 38
hyperslug Avatar answered Nov 15 '22 08:11

hyperslug