Friday, December 6, 2013

Part IV: Access the backend datastore

Folks, what's going on? To night we gonna have party? Just kidding, we talk about serious stuff.
After all our app reads the input, but what should we do with these values? Easy!
Save it to the app engine datastore.
In first place we add some imports
"appengine", "appengine/datastore" 
also setup a struct for our entity finally we introduce two new functions one named
saveToDatastore(f Food, r *http.Request) bool
and second
mealStoreKey(c appengine.Context) *datastore.Key .

I added some more comments to the code.


package mycanteen
   
import(
 "net/http"
 "html/template"
 "strconv"
 "fmt"
 "appengine"
 "appengine/datastore"
)

type Food struct{
 Course string
 Name string 
 Date string
 Price float64
}
   
// No main function. Go App Engine use the init-func
func init() {
    http.HandleFunc("/", root)
    http.HandleFunc("/admin", admin);
    http.HandleFunc("/save", save)
}
   
func root(w http.ResponseWriter, r *http.Request) {    
    // Here we will add the Userpanel, but not know 
}
 
/*********************ADMINPANEL HANDLER**************************/
func admin(w http.ResponseWriter, r *http.Request) {      
    // Execute the parsing. We pass the ResponseWriter and a second value, which should be fill the gaps at the template. 
    // We have no gaps, so we have nothing to fill in. 
    if err := adminPanelTemplate.Execute(w, ""); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}
/********************SAVE/PERSIST HANDLER************************/
func save(w http.ResponseWriter, r *http.Request) {    


    // You have to parse the form from our admin panel. It's mandatory!
    if err := r.ParseForm(); err != nil {
     fmt.Fprint(w,err) 
    }
     
    // Now we a readey to get the fish ;-)
    course := r.FormValue("course")
    name := r.FormValue("name")
    date := r.FormValue("date")
    // The form is string based, for later purpose we parse it to float
    price, _ := strconv.ParseFloat(r.FormValue("price"), 64)
    
    f := Food{course,name,date,price,}
    // Persist to Datastore
    // At this moment we cant save the values, hence we setup only this output to check the values.
    if  saveToDatastore(f,r) == true{
     fmt.Fprintf(w, "You \"saved\" successfully: Our first %s %s costs %v %s on %s", course,name,price,string(0x20AC),date)
    }else{
        fmt.Fprintf(w, "Error happens, can't persist to database")
    }
 
}

func saveToDatastore(f Food, r *http.Request) bool{
 // Get context from 
    c := appengine.NewContext(r);

    key := datastore.NewIncompleteKey(c, "Meal", mealStoreKey(c))
    _, err := datastore.Put(c, key, &f)
    if err != nil{
 return false
    }else{
 return true
    }
}

// foodKey returns the key used for all food entries.
func mealStoreKey(c appengine.Context) *datastore.Key {
    // The string "default_food" here could be varied to have multiple cantines.
    return datastore.NewKey(c, "MealStore", "meal", 0, nil)
}
 
// Parse the HTMLTemplate, despite it is not neccesary yet.
var adminPanelTemplate = template.Must(template.New("adminPanelHTML").Parse(adminPanelHTML))
   
// Here you define the HTML which will be parsed.
const adminPanelHTML= `
<html>
<head>
</head>
<body>
Name: Price: Date:
</body> </html> `
mealStoreKey: This function returns a key used for all meal structs (entities) saveToDataStore: At this place we do the magic. We pass it a new, incomplete key so that the datastore will create a new key for this record automatically. Finally store it to the backend. Here are the evidence:

htpp://localhost:8000

See ya tommorrow!

No comments:

Post a Comment