はじめに
GAEをGinを利用して構築していきます。
HTML フォームデータの処理(GAE/Go/Gin)の続きです。
流れは、公式サイトのデータの保存と同じです。
ソース
今回のフォルダ構成は、以下の通りです。
├── template
│ └── index.html
├── static
│ ├── style.css
│ └── gcp-gopher.svg
├── app.yaml
└── main.go
app.yaml
runtime: go111
handlers:
- url: /static
static_dir: static
- url: /.*
script: auto
style.css
body {
font-family: Arial, sans-serif;
color: blue;
}
Ginを利用しており、GETメソッドと POSTメソッドで呼び出すハンドラーを分けています。
main.go
package main
import (
"fmt"
"net/http"
"time"
"github.com/gin-gonic/gin"
"google.golang.org/appengine"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine/log"
)
type Post struct {
Author string
Message string
Posted time.Time
}
type templateParams struct {
Notice string
Name string
Message string
Posts []Post
}
func main() {
router := gin.Default()
router.LoadHTMLGlob("template/*") // 事前にテンプレートをロード(相対パス)
router.GET("/", indexGetHandle)
router.POST("/", indexPostHandle)
http.Handle("/", router) // router.Run(":8080")の代わり
appengine.Main() // これがないと動かない
}
func indexGetHandle(c *gin.Context) {
ctx := appengine.NewContext(c.Request)
params := templateParams{}
q := datastore.NewQuery("Post").Order("-Posted").Limit(20)
if _, err := q.GetAll(ctx, ¶ms.Posts); err != nil {
log.Errorf(ctx, "Getting posts: %v", err)
params.Notice = "Couldn't get latest posts. Refresh?"
c.HTML(http.StatusInternalServerError, "top/index", gin.H{
"params": params,
})
return
}
c.HTML(http.StatusOK, "top/index", gin.H{
"params": params,
})
}
func indexPostHandle(c *gin.Context) {
ctx := appengine.NewContext(c.Request)
params := templateParams{}
post := Post{
Author: c.PostForm("name"),
Message: c.PostForm("message"),
Posted: time.Now(),
}
if post.Author == "" {
post.Author = "Anonymous Gopher"
}
params.Name = post.Author
if post.Message == "" {
params.Notice = "No message provided"
c.HTML(http.StatusBadRequest, "top/index", gin.H{
"params": params,
})
return
}
key := datastore.NewIncompleteKey(ctx, "Post", nil)
if _, err := datastore.Put(ctx, key, &post); err != nil {
log.Errorf(ctx, "datastore.Put: %v", err)
params.Notice = "Couldn't add new post. Try again?"
params.Message = post.Message // Preserve their message so they can try again.
c.HTML(http.StatusInternalServerError, "top/index", gin.H{
"params": params,
})
return
}
params.Posts = append([]Post{post}, params.Posts...)
params.Notice = fmt.Sprintf("Thank you for your submission, %s!", post.Author)
c.HTML(http.StatusOK, "top/index", gin.H{
"params": params,
})
}
変数指定で、「.params」がないと動作しませんでした。
template/index.html
{{ define "top/index" }}
<!doctype html>
<html>
<head>
<title>The Gopher Network</title>
<link rel="stylesheet" type="text/css" href="/static/style.css">
</head>
<body>
<h1>The Gopher Network</h1>
<img id="logo" src="/static/gcp-gopher.svg" width="100">
{{with .params.Notice}}<div id="notice">{{.}}</div>{{end}}
<form action="/" method="post">
<div>Name: <input name="name" value="{{.params.Name}}"></div>
<div>Message: <input name="message"></div>
<input type="submit">
</form>
{{with .params.Posts}}
<ol>
{{range . }}
<li><cite>{{.Author}}</cite><p>{{.Message}}</p></li>
{{end}}
</ol>
{{end}}
</body>
</html>
{{ end }}
ローカルで実行
dev_appserver.py app.yaml
localhost:8080
にアクセスすると以下の画面が表示されます。
データは、どこに登録されれいるのだろう??
アプリケーションをデプロイする
gcloud app deploy
アプリケーションを表示する
gcloud app browse
その後、http://[YOUR_PROJECT_ID].appspot.com
で、画面が表示されるかを確認します。
メッセージ送付後
データは、Datastoreに保存されてました。
ローカル起動時のデータが何処に保存されているのか不明