//save article and save tags transaction func (this *ArticleMetaData) Save(ctx Context) (err error) { c := ctx.GAEContext uuid, err := GenUUID() if err != nil { return err } this.Id = uuid k := datastore.NewKey(c, "Article", uuid, 0, nil) err = datastore.RunInTransaction(c, func(c appengine.Context) error { if len(this.Tags) > 0 { tags := make([]Tags, len(this.Tags)) tagsKey := make([]*datastore.Key, len(this.Tags)) for id, tag := range this.Tags { tags[id].ArticleId = uuid tags[id].Tag = tag tagId := uuid + tag tagsKey[id] = datastore.NewKey(c, "Tags", tagId, 0, nil) } _, err = datastore.PutMulti(c, tagsKey, tags) if err != nil { return err } } _, err = datastore.Put(c, k, this) return err }, &datastore.TransactionOptions{XG: true}) return err }
func showFeed(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) url, err := url.QueryUnescape(r.URL.RawQuery) if err != nil { handleError(w, err) return } feedRoot := datastore.NewKey(c, "feedRoot", "feedRoot", 0, nil) fk := datastore.NewKey(c, "feed", url, 0, feedRoot) f := new(RSS) err = datastore.Get(c, fk, f) if err != nil { handleError(w, err) return } _, err = datastore.NewQuery("item").Ancestor(fk).Order("-PubDate").GetAll(c, &f.Items) if err != nil { handleError(w, err) return } templ, err := template.New("showFeed").Parse(feedPageRaw) if err != nil { handleError(w, err) return } err = templ.Execute(w, f) if err != nil { handleError(w, err) return } }
func (sto *appengineStorage) EnumerateBlobs(ctx context.Context, dest chan<- blob.SizedRef, after string, limit int) error { defer close(dest) loan := ctxPool.Get() defer loan.Return() actx := loan prefix := sto.namespace + "|" keyBegin := datastore.NewKey(actx, memKind, prefix+after, 0, nil) keyEnd := datastore.NewKey(actx, memKind, sto.namespace+"~", 0, nil) q := datastore.NewQuery(memKind).Limit(int(limit)).Filter("__key__>", keyBegin).Filter("__key__<", keyEnd) it := q.Run(actx) var row memEnt for { key, err := it.Next(&row) if err == datastore.Done { break } if err != nil { return err } select { case dest <- blob.SizedRef{blob.ParseOrZero(key.StringID()[len(prefix):]), uint32(row.Size)}: case <-ctx.Done(): return ctx.Err() } } return nil }
func newGrid(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) title := r.FormValue("title") rows := strings.Split(r.FormValue("rows"), "\n") cols := strings.Split(r.FormValue("cols"), "\n") key := newKey() k := datastore.NewKey(c, "grid", key, 0, nil) g := new(Grid) g.Id = key g.Title = title _, err := datastore.Put(c, k, g) if err != nil { c.Errorf("error adding grid: %v", err) } for i, r := range rows { rkey := datastore.NewKey(c, "row", newKey(), 0, nil) row := new(Row) row.Grid = k row.Label = strings.TrimSpace(r) row.DisplayOrder = i _, err := datastore.Put(c, rkey, row) c.Errorf("added row %v", err) } for i, co := range cols { ckey := datastore.NewKey(c, "col", newKey(), 0, nil) col := new(Col) col.Grid = k col.Label = strings.TrimSpace(co) col.DisplayOrder = i _, err := datastore.Put(c, ckey, col) c.Errorf("added col %v", err) } http.Redirect(w, r, "/grid/"+key, http.StatusFound) }
func read(c appengine.Context, name string) (fi *FileInfo, data []byte, err error) { name, _, _ = mangle(c, name) fi1, err := stat(c, name) if err != nil { return nil, nil, err } if fi1.IsDir { dt, err := readdir(c, name) if err != nil { return nil, nil, err } fi = fi1 data = dt return fi, data, nil } root := datastore.NewKey(c, "RootKey", "v2:", 0, nil) dkey := datastore.NewKey(c, "FileData", "", fi1.Qid, root) var fd FileData c.Infof("DATASTORE Read %q", name) if err := datastore.Get(c, dkey, &fd); err != nil { return nil, nil, err } fi = fi1 data = fd.Data return fi, data, nil }
func (cfg *Config) Key(c appengine.Context, parent *datastore.Key) *datastore.Key { if parent == nil { u := user.Current(c) parent = datastore.NewKey(c, userTabName, u.String(), 0, nil) } return datastore.NewKey(c, configTableName, cfg.Name, 0, parent) }
func (sto *appengineStorage) EnumerateBlobs(dest chan<- blob.SizedRef, after string, limit int, wait time.Duration) error { defer close(dest) ctx := sto.ctx if ctx == nil { loan := ctxPool.Get() defer loan.Return() ctx = loan } prefix := sto.namespace + "|" keyBegin := datastore.NewKey(ctx, memKind, prefix+after, 0, nil) keyEnd := datastore.NewKey(ctx, memKind, sto.namespace+"~", 0, nil) q := datastore.NewQuery(memKind).Limit(int(limit)).Filter("__key__>", keyBegin).Filter("__key__<", keyEnd) it := q.Run(ctx) var row memEnt for { key, err := it.Next(&row) if err == datastore.Done { break } if err != nil { return err } dest <- blob.SizedRef{blob.ParseOrZero(key.StringID()[len(prefix):]), row.Size} } return nil }
func TouchSuc(c appengine.Context, IdSuc string, IdEmp string) error { /* llave de Cta-Empresa */ ce := &CtaEmpresa{IdEmp: IdEmp} ceKey := datastore.NewKey(c, "CtaEmpresa", ce.IdEmp, 0, nil) err := datastore.Get(c, ceKey, ce) if err == datastore.ErrNoSuchEntity { return nil } /* parent de Empresa */ cta := &Cta{Email: ce.Email} ctaKey := datastore.NewKey(c, "Cta", cta.Email, 0, nil) err = datastore.Get(c, ctaKey, cta) if err == datastore.ErrNoSuchEntity { return nil } /* Key de empresa */ empKey := datastore.NewKey(c, "Empresa", IdEmp, 0, ctaKey) suc := &Sucursal{IdSuc: IdSuc} sucKey := datastore.NewKey(c, "Sucursal", IdSuc, 0, empKey) err = datastore.Get(c, sucKey, suc) if err == datastore.ErrNoSuchEntity { return err } suc.FechaHora = time.Now().Add(time.Duration(GMTADJ) * time.Second) if _, err = datastore.Put(c, sucKey, suc); err != nil { return err } return nil }
// Increment increments the named counter. func Increment(c appengine.Context, name string) error { // Get counter config. var cfg counterConfig ckey := datastore.NewKey(c, configKind, name, 0, nil) err := datastore.RunInTransaction(c, func(c appengine.Context) error { err := datastore.Get(c, ckey, &cfg) if err == datastore.ErrNoSuchEntity { cfg.Shards = defaultShards _, err = datastore.Put(c, ckey, &cfg) } return err }, nil) if err != nil { return err } err = datastore.RunInTransaction(c, func(c appengine.Context) error { shardName := fmt.Sprintf("%v%d", name, rand.Intn(cfg.Shards)) key := datastore.NewKey(c, shardKind, shardName, 0, nil) var s shard err := datastore.Get(c, key, &s) // A missing entity and a present entity will both work. if err != nil && err != datastore.ErrNoSuchEntity { return err } s.Count++ s.Name = name _, err = datastore.Put(c, key, &s) return err }, nil) if err != nil { return err } //memcache.Increment(c, memcacheKey(name), 1, 0) return nil }
// Métodos de Empresa func GetEmpresa(c appengine.Context, id string) *Empresa { /* llave de Cta-Empresa */ ce := &CtaEmpresa{IdEmp: id} ceKey := datastore.NewKey(c, "CtaEmpresa", ce.IdEmp, 0, nil) err := datastore.Get(c, ceKey, ce) if err == datastore.ErrNoSuchEntity { return nil } /* parent de Empresa */ cta := &Cta{Email: ce.Email} ctaKey := datastore.NewKey(c, "Cta", cta.Email, 0, nil) err = datastore.Get(c, ctaKey, cta) if err == datastore.ErrNoSuchEntity { return nil } /* Key de empresa */ emp := &Empresa{IdEmp: id} empKey := datastore.NewKey(c, "Empresa", emp.IdEmp, 0, ctaKey) err = datastore.Get(c, empKey, emp) if err == datastore.ErrNoSuchEntity { return nil } return emp }
func GetEmpSucursales(c appengine.Context, IdEmp string) *[]Sucursal { /* llave de Cta-Empresa */ ce := &CtaEmpresa{IdEmp: IdEmp} ceKey := datastore.NewKey(c, "CtaEmpresa", ce.IdEmp, 0, nil) err := datastore.Get(c, ceKey, ce) if err == datastore.ErrNoSuchEntity { return nil } /* parent de Empresa */ cta := &Cta{Email: ce.Email} ctaKey := datastore.NewKey(c, "Cta", cta.Email, 0, nil) err = datastore.Get(c, ctaKey, cta) if err == datastore.ErrNoSuchEntity { return nil } /* Key de empresa */ empKey := datastore.NewKey(c, "Empresa", IdEmp, 0, ctaKey) q := datastore.NewQuery("Sucursal").Ancestor(empKey) n, _ := q.Count(c) sucursales := make([]Sucursal, 0, n) if _, err := q.GetAll(c, &sucursales); err != nil { return nil } return &sucursales }
func registration(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) u := User{ Name: "TestHendrik", StartDate: datastore.SecondsToTime(time.Seconds()), } if g := user.Current(c); g != nil { var u2 User u.Account = g.String() if err := datastore.Get(c, datastore.NewKey("user", g.String(), 0, nil), &u2); err == datastore.ErrNoSuchEntity { key, err := datastore.Put(c, datastore.NewKey("user", u.Account, 0, nil), &u) if err != nil { http.Error(w, err.String(), http.StatusInternalServerError) return } fmt.Fprintf(w, "User %q stored %q", u.Account, key) return } else { fmt.Fprintf(w, "User %q is already logged in", g.String()) return } } else { url, err := user.LoginURL(c, r.URL.String()) if err != nil { http.Error(w, err.String(), http.StatusInternalServerError) return } w.Header().Set("Location", url) w.WriteHeader(http.StatusFound) return } }
// chat部屋にいるメンバリストに相当するAncestorKeyを返す func memberKey(c appengine.Context, key string) *datastore.Key { if key == "" { return datastore.NewKey(c, "Member", "default_member", 0, nil) } else { return datastore.NewKey(c, "Member", key, 0, nil) } }
func (this *ArticleMetaData) Delete(ctx Context) (err error) { c := ctx.GAEContext k := datastore.NewKey(c, "Article", this.Id, 0, nil) err = datastore.RunInTransaction(c, func(c appengine.Context) error { err = datastore.Get(c, k, this) if err != nil { return err } if len(this.Tags) > 0 { tags := make([]Tags, len(this.Tags)) tagsKey := make([]*datastore.Key, len(this.Tags)) for id, tag := range this.Tags { tags[id].ArticleId = this.Id tags[id].Tag = tag tagId := this.Id + tag tagsKey[id] = datastore.NewKey(c, "Tags", tagId, 0, nil) } err = datastore.DeleteMulti(c, tagsKey) if err != nil { return err } } err = datastore.Delete(c, k) return err }, &datastore.TransactionOptions{XG: true}) return err }
func (d *DatastoreStorage) StorePosts(req *http.Request, posts []blogplus.Activity) { c := appengine.NewContext(req) var keys []*datastore.Key var src []interface{} for _, post := range posts { if d.filter != nil && !d.filter(post) { c.Debugf("ignore post:%s", post.Id) continue } datespec := blogplus.GetDatespec(post.Published) data, err := blogplus.EncodeActivity(post) if err != nil { c.Errorf("encode error:%#v", err) continue } c.Infof("store %s datespec %s", post.Id, datespec) datekey := datastore.NewKey(c, activityRef, post.Id, 0, datastore.NewKey(c, datespecKind, datespec, 0, nil)) key := datastore.NewKey(c, activityKind, post.Id, 0, nil) keys = append(keys, datekey) src = append(src, &DatespecEntity{Id: key}) keys = append(keys, key) src = append(src, &ActivityEntity{ Id: post.Id, Published: post.Published, Post: data}) } _, err := datastore.PutMulti(c, keys, src) if err != nil { c.Errorf("put error:%#v", err) } }
func addAtom(c appengine.Context, url string) error { feedRoot := datastore.NewKey(c, "feedRoot", "feedRoot", 0, nil) fk := datastore.NewKey(c, "feed", url, 0, feedRoot) err := datastore.RunInTransaction(c, func(c appengine.Context) error { done, err := exists(c, fk) if err != nil { return err } if !done { f, err := fetchAtom(c, url) if err != nil { return err } _, err = datastore.Put(c, fk, f) if err != nil { return err } err = f.update(c, fk) if err != nil { return err } return nil } return nil }, nil) if err != nil { return err } return subscribe(c, fk, true) }
/* This call deletes and creates unit-testing data. */ func (h *System) CreateTestData(r *http.Request, args *SystemArgs, reply *GeneralReply) error { c := appengine.NewContext(r) var err error // delete any previous testing data { var keys_to_delete []*datastore.Key REGION_UIDS_TO_DELETE := []string{"@test-san-francisco", "@test-los-angeles"} RESTAURANT_UIDS_TO_DELETE := []string{"@test-mcdonalds", "@test-In-N-Out", "@test-Wendys"} TAGS_UIDS_TO_DELETE := []string{"@test-american", "@test-french"} for _, uid := range REGION_UIDS_TO_DELETE { q := datastore.NewQuery("Tags").Filter("Uid =", uid).KeysOnly() keys_to_delete, err = q.GetAll(c, nil) checkErr(err, "DB error1") err = datastore.DeleteMulti(c, keys_to_delete) checkErr(err, "DB error2") } for _, uid := range RESTAURANT_UIDS_TO_DELETE { q := datastore.NewQuery("Region").Filter("Uid =", uid).KeysOnly() keys_to_delete, err = q.GetAll(c, nil) checkErr(err, "DB error3") err = datastore.DeleteMulti(c, keys_to_delete) checkErr(err, "DB error4") } for _, uid := range TAGS_UIDS_TO_DELETE { q := datastore.NewQuery("Restaurant").Filter("Uid =", uid).KeysOnly() _, err = q.GetAll(c, &keys_to_delete) checkErr(err, "DB error5") err = datastore.DeleteMulti(c, keys_to_delete) checkErr(err, "DB error6") } log.Printf("... cleanup done") } // re-create the data (unless this was a cleanup operation only) if !args.CleanupOnly { region1 := models.Region{Uid: "@test-san-francisco", Title: "TEST San Francisco"} _, err = datastore.Put(c, datastore.NewKey(c, "Region", region1.Uid, 0, nil), ®ion1) checkErr(err, "fail trying to insert") region2 := models.Region{Uid: "@test-los-angeles", Title: "TEST Los Angeles"} _, err = datastore.Put(c, datastore.NewKey(c, "Region", region2.Uid, 0, nil), ®ion2) checkErr(err, "fail trying to insert") restaurant1 := models.Restaurant{Uid: "@test-mcdonalds", Title: "TEST McDonalds", Tags: []string{"French Cuisine", "American"}, Regions: []string{region1.Uid}} _, err = datastore.Put(c, datastore.NewKey(c, "Restaurant", restaurant1.Uid, 0, nil), &restaurant1) checkErr(err, "fail trying to insert") restaurant2 := models.Restaurant{Uid: "@test-In-N-Out", Tags: []string{"American"}, Regions: []string{region1.Uid, region2.Uid}} _, err = datastore.Put(c, datastore.NewKey(c, "Restaurant", restaurant2.Uid, 0, nil), &restaurant2) checkErr(err, "fail trying to insert") restaurant3 := models.Restaurant{Uid: "@test-Wendys", Tags: []string{"American"}, Regions: []string{region2.Uid}} _, err = datastore.Put(c, datastore.NewKey(c, "Restaurant", restaurant3.Uid, 0, nil), &restaurant3) checkErr(err, "fail trying to insert") log.Printf("... creation done") } return nil }
// logHandler displays log text for a given hash. // It handles paths like "/log/hash". func logHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-type", "text/plain; charset=utf-8") c := contextForRequest(r) hash := r.URL.Path[strings.LastIndex(r.URL.Path, "/")+1:] key := datastore.NewKey(c, "Log", hash, 0, nil) l := new(Log) if err := datastore.Get(c, key, l); err != nil { if err == datastore.ErrNoSuchEntity { // Fall back to default namespace; // maybe this was on the old dashboard. c := appengine.NewContext(r) key := datastore.NewKey(c, "Log", hash, 0, nil) err = datastore.Get(c, key, l) } if err != nil { logErr(w, r, err) return } } b, err := l.Text() if err != nil { logErr(w, r, err) return } w.Write(b) }
// UserKey to identify App Engine User func UserKey(c appengine.Context) *datastore.Key { u := user.Current(c) if u == nil { return datastore.NewKey(c, "User", "Anonymous", 0, nil) } return datastore.NewKey(c, "User", u.Email, 0, nil) }
func NewUser(r *http.Request, id string, email string, name string, provider string) (*User, error) { c := appengine.NewContext(r) // create new user userId, _, _ := datastore.AllocateIDs(c, "User", nil, 1) key := datastore.NewKey(c, "User", "", userId, nil) user := User{userId, email, name, time.Now()} _, err := datastore.Put(c, key, &user) if err != nil { return nil, err } // create external authentication externalAuthId, _, _ := datastore.AllocateIDs(c, "ExternalAuth", nil, 1) key = datastore.NewKey(c, "ExternalAuth", "", externalAuthId, nil) externalAuth := ExternalAuth{externalAuthId, id, userId, provider} _, err = datastore.Put(c, key, &externalAuth) if err != nil { return nil, err } return &user, err }
func addCol(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) parts := strings.Split(r.URL.String(), "/") if len(parts) < 3 { http.Error(w, "bad request", 404) return } gridkey := parts[2] k := datastore.NewKey(ctx, "grid", gridkey, 0, nil) cq := datastore.NewQuery("col").Filter("Grid=", k).Order("DisplayOrder") cols := make([]Col, 0, 100) _, err := cq.GetAll(ctx, &cols) if err != nil { // handle the error ctx.Errorf("cols fetch: %v", err) } var maxOrder = 0 for _, col := range cols { if col.DisplayOrder > maxOrder { maxOrder = col.DisplayOrder } } ckey := datastore.NewKey(ctx, "col", newKey(), 0, nil) col := new(Col) col.Grid = k col.Label = strings.TrimSpace(r.FormValue("label")) col.DisplayOrder = maxOrder + 1 _, err = datastore.Put(ctx, ckey, col) ctx.Errorf("added col %v", err) http.Redirect(w, r, "/grid/"+gridkey, http.StatusFound) }
func (f FeedInfo) updateArticles(c appengine.Context, articles Articles) error { key := datastore.NewKey(c, feedKind, f.Url, 0, nil) q := datastore.NewQuery(articleKind).Ancestor(key).KeysOnly() stored := make(map[string]*datastore.Key) for it := q.Run(c); ; { k, err := it.Next(nil) if err == datastore.Done { break } else if err != nil { return err } stored[k.StringID()] = k } for _, a := range articles { k := datastore.NewKey(c, articleKind, a.StringID(), 0, key) id := k.StringID() if _, ok := stored[id]; ok { delete(stored, id) continue } if _, err := datastore.Put(c, k, &a); err != nil { return err } } for _, k := range stored { if err := datastore.Delete(c, k); err != nil { return err } } return nil }
func addRow(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) parts := strings.Split(r.URL.String(), "/") if len(parts) < 3 { http.Error(w, "bad request", 404) return } gridkey := parts[2] k := datastore.NewKey(ctx, "grid", gridkey, 0, nil) rq := datastore.NewQuery("row").Filter("Grid=", k).Order("DisplayOrder") rows := make([]Row, 0, 100) _, err := rq.GetAll(ctx, &rows) if err != nil { // handle the error ctx.Errorf("rows fetch: %v", err) } var maxOrder = 0 for _, row := range rows { if row.DisplayOrder > maxOrder { maxOrder = row.DisplayOrder } } rkey := datastore.NewKey(ctx, "row", newKey(), 0, nil) row := new(Row) row.Grid = k row.Label = strings.TrimSpace(r.FormValue("label")) row.DisplayOrder = maxOrder + 1 _, err = datastore.Put(ctx, rkey, row) ctx.Errorf("added row %v", err) http.Redirect(w, r, "/grid/"+gridkey, http.StatusFound) }
// RTTResolver returns a Sliver from a Site with lowest RTT given a client's IP. func RTTResolver(c appengine.Context, toolID string, ip net.IP) (net.IP, error) { cgIP := rtt.GetClientGroup(ip).IP rttKey := datastore.NewKey(c, "string", "rtt", 0, nil) key := datastore.NewKey(c, "ClientGroup", cgIP.String(), 0, rttKey) // Get ClientGroup from datastore. var cg rtt.ClientGroup err := data.GetData(c, MCKey_ClientGroup(cgIP), key, &cg) if err != nil { if err == datastore.ErrNoSuchEntity { return nil, ErrNotEnoughData } return nil, err } // Get first error-less Site and a random SliverTool from selected Site. var siteID string var sliverTool *data.SliverTool for _, sr := range cg.SiteRTTs { siteID = sr.SiteID sliverTool, err = data.GetRandomSliverFromSite(c, toolID, siteID) if err == nil { return net.ParseIP(sliverTool.SliverIPv4), nil } } // No valid Site found. return nil, ErrNotEnoughData }
func (sto *appengineStorage) EnumerateBlobs(dest chan<- blobref.SizedBlobRef, after string, limit uint, waitSeconds int) os.Error { defer close(dest) if sto.ctx == nil { return errNoContext } prefix := sto.namespace + "|" keyBegin := datastore.NewKey(sto.ctx, memKind, prefix+after, 0, nil) keyEnd := datastore.NewKey(sto.ctx, memKind, sto.namespace+"~", 0, nil) q := datastore.NewQuery(memKind).Limit(int(limit)).Filter("__key__>", keyBegin).Filter("__key__<", keyEnd) it := q.Run(sto.ctx) var row memEnt for { key, err := it.Next(&row) if err == datastore.Done { break } if err != nil { return err } size, err := row.size() if err != nil { return err } dest <- blobref.SizedBlobRef{blobref.Parse(key.StringID()[len(prefix):]), size} } return nil }
// 勉強会の追加 func (group *Group) Add(c appengine.Context) os.Error { count := new(Counter) countKey := datastore.NewKey(c, "Counter", "mycounter", 0, nil) countErr := datastore.RunInTransaction(c, func(c appengine.Context) os.Error { err := datastore.Get(c, countKey, count) if err != nil && err != datastore.ErrNoSuchEntity { return err } count.GroupCount++ _, err = datastore.Put(c, countKey, count) return err }, nil) if countErr != nil { return countErr } group.Id = count.GroupCount group.CreateDate = datastore.SecondsToTime(time.Seconds()) key := datastore.NewKey(c, "Group", "", int64(group.Id), nil) _, err := datastore.Put(c, key, group) return err }
func addToInbox(c appengine.Context, userid string, perma_blobref string, seq int64) (err os.Error) { // Store it b := inboxStruct{LastSeq: seq} parent := datastore.NewKey("user", userid, 0, nil) _, err = datastore.Put(c, datastore.NewKey("inbox", perma_blobref, 0, parent), &b) return err }
func updateSubscriberCount(c appengine.Context, feedURL string, delta int) error { err := datastore.RunInTransaction(c, func(c appengine.Context) error { shardName := fmt.Sprintf("%s#%d", feedURL, rand.Intn(subscriberCountShards)) key := datastore.NewKey(c, "SubscriberCountShard", shardName, 0, nil) var shard subscriberCountShard if err := datastore.Get(c, key, &shard); err == datastore.ErrNoSuchEntity { shard.Feed = datastore.NewKey(c, "Feed", feedURL, 0, nil) } else if err != nil { return err } shard.SubscriberCount += delta _, err := datastore.Put(c, key, &shard) return err }, nil) if err != nil { return err } return nil }
func getNoteChunk(c appengine.Context, notebookID int64, period string) (*datastore.Key, NoteChunk, error) { var chunk NoteChunk notebookKey := datastore.NewKey(c, "Notebook", "", notebookID, nil) chunkKey := datastore.NewKey(c, "NoteChunk", period, 0, notebookKey) err := datastore.Get(c, chunkKey, &chunk) return chunkKey, chunk, err }
// articlePost handles saving new/edited pages in the admin manager. It // generates the Article struct based on data submitted by the client, and // then puts it into the datastore. // TODO: Don't need to manually delete old instance, can simply replace it, // so skip that step! func articlePost(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) // Create the article struct based on form data a := Article{ ID: r.FormValue("OldID"), // This may or may not be blank Title: r.FormValue("Title"), Author: user.Current(c).String(), Date: datastore.SecondsToTime(time.Seconds()), Public: true, // TODO: Implement public/private ShortBody: []byte(r.FormValue("ShortBody")), Body: []byte(r.FormValue("Body")), } a.DisplayDate = a.Date.Time().Format("Jan 2") // Set exposed date // If a.ID isn't blank, that means we're updating an article if a.ID != "" { // TODO: Need to remove the delete, and verify things still work err := datastore.Delete(c, datastore.NewKey(c, "Article", a.ID, 0, nil)) check(err) } else { a.ID = newArticleID() } // Add the Article struct to the datastore _, err := datastore.Put(c, datastore.NewKey(c, "Article", a.ID, 0, nil), &a) check(err) // Prints the article back to the client upon access (should come up with // a better way to express success!) fmt.Fprintf(w, "Article: %v\n", a) }