はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。
GoのフレームワークであるGinを中心に、
webアプリ開発学習をしていきます。
バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。
本日の学習内容
GinのTutorialで作成したAPIを改造して、簡素なWebアプリを作成しようと思います
- GinとGORMを使用したAPIをHTMLに連動 ←Topics!!
GinとGORMを使用したAPIをHTMLに連動
先日GORMを使用してDBと連動させたAPIをHTMLファイルとつなげて、
Webから操作できるようにしました。
db.Closeが書かれているコードもありますが、
POST後のRedirect時などに正常に反応しなかったのでCloseはしてません。
正常に反応する修正方法等、アドバイスあればいただきたいです。
main.go
package main
import (
"ginapp-albums/app/controllers"
"ginapp-albums/app/models"
)
func main() {
dbConn := models.DbInit()
controllers.NewRoutes(dbConn)
}
}
app/models
albumdb.go
package models
import (
"github.com/jinzhu/gorm"
)
// Connstruct Album struct
type Album struct {
gorm.Model
Title string `json:"title" form:"title"`
Artist string `json:"artist" form:"artist"`
Price float64 `json:"price" form:"price"`
}
base.go
package models
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
//Initialized DB
func DbInit() *gorm.DB {
var dsn = "user:password@/DBNAME?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open("mysql", dsn)
if err != nil {
panic("failed connecting DB")
}
db.LogMode(true)
db.AutoMigrate(&Album{})
return db
}
app/controllers
webserver.go
package controllers
import (
"ginapp-albums/app/models"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
)
type AlbumHandler struct {
Db *gorm.DB
}
func (h *AlbumHandler) GetAlbums() []models.Album {
var albums []models.Album
h.Db.Find(&albums)
return albums
}
func (h *AlbumHandler) InsertAlbums(c *gin.Context) {
var albumRequest models.Album
if err := c.Bind(&albumRequest); err != nil {
albums := h.GetAlbums()
c.HTML(http.StatusBadRequest, "index.html", gin.H{"albums": albums, "err": err})
c.Abort()
} else {
title, _ := c.GetPostForm("title")
artist, _ := c.GetPostForm("artist")
price, _ := c.GetPostForm("price")
floatprice, _ := strconv.ParseFloat(price, 64)
h.Db.Create(&models.Album{Title: title, Artist: artist, Price: floatprice})
c.Redirect(http.StatusMovedPermanently, "/albums")
}
}
func (h *AlbumHandler) GetAlbumByID(c *gin.Context) {
id := c.Param("id")
checkId, err := strconv.Atoi(id)
if err != nil {
panic(err)
}
album := models.Album{}
h.Db.First(&album, checkId)
c.HTML(http.StatusOK, "update.html", gin.H{"album": album})
}
func (h *AlbumHandler) UpdateAlbumByID(c *gin.Context) {
id := c.Param("id")
checkId, err := strconv.Atoi(id)
if err != nil {
panic(err)
}
var album models.Album
var albumRequest models.Album
if err := c.Bind(&albumRequest); err != nil {
albums := h.GetAlbums()
c.HTML(http.StatusBadRequest, "index.html", gin.H{"albums": albums, "err": err})
c.Abort()
} else {
title, _ := c.GetPostForm("title")
artist, _ := c.GetPostForm("aritst")
price, _ := c.GetPostForm("price")
floatprice, _ := strconv.ParseFloat(price, 64)
h.Db.First(&album, checkId)
album.Title = title
album.Artist = artist
album.Price = floatprice
h.Db.Save(&album)
c.Redirect(http.StatusMovedPermanently, "/albums")
}
}
func (h *AlbumHandler) DeleteAlbumByID(c *gin.Context) {
id := c.Param("id")
checkId, err := strconv.Atoi(id)
if err != nil {
panic(err)
}
var album models.Album
h.Db.First(&album, checkId)
h.Db.Delete(&album)
c.Redirect(http.StatusMovedPermanently, "/albums")
}
route.go
package controllers
import (
"net/http"
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
)
func NewRoutes(dbConn *gorm.DB) {
albumHandler := AlbumHandler{
Db: dbConn,
}
router := gin.Default()
router.Use(cors.New(cors.Config{
AllowOrigins: []string{"*"},
AllowMethods: []string{"PUT", "PATCH", "DELETE", "POST", "GET"},
AllowHeaders: []string{"Origin"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
AllowOriginFunc: func(origin string) bool {
return origin == "*"
},
MaxAge: 12 * time.Hour,
}))
router.LoadHTMLGlob("app/views/*.html")
router.GET("/albums", func(c *gin.Context) {
albums := albumHandler.GetAlbums()
c.HTML(http.StatusOK, "index.html", gin.H{"albums": albums})
})
router.GET("/albums/:id", albumHandler.GetAlbumByID)
router.POST("/albums/new", albumHandler.InsertAlbums)
router.POST("/albums/update/:id", albumHandler.UpdateAlbumByID)
router.POST("/albums/delete/:id", albumHandler.DeleteAlbumByID)
router.Run("localhost:8080")
}
app/views
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>AlbumsList</title>
</head>
<body>
<h1><a href="/albums">AlbumListApp</a></h1>
<h2>Add Album</h2>
<form method="POST" action="/albums/new">
<p>Title <input type="text" name="title" value="{{.album.Title}}" size="30" placeholder="Input Title"></p>
<p>Artist <input type="text" name="artist" value="{{.album.Artist}}" size="30" placeholder="Input Artist"></p>
<p>Price <input type="text" name="price" value="{{.album.Price}}" size="30" placeholder="Input Price"></p>
<p><input type="submit" value="Send"></p>
</form>
<ul>
{{ range .albums }}
<li>ID:{{ .ID }} Title:{{ .Title }} Artist:{{ .Artist }} Price:{{ .Price }}
<label><a href="/albums/{{.ID}}">UPDATE</a></label>
<label><form action="/albums/delete/{{.ID}}" method="POST"><input type="submit" value="DELETE"></form></label>
</li>
{{end}}
</ul>
</body>
</html>
update.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>UpdateAlbum</title>
</head>
<body>
<h1><a href="/albums">AlbumListApp</a></h1>
<h2>Update Album</h2>
<p>ID:{{ .album.ID }}</p>
<p>Title:{{ .album.Title }}</p>
<p>Artist:{{ .album.Artist }}</p>
<p>Price:{{ .album.Price }}</p>
<h3>Edit</h3>
<form method="POST" action="/albums/update/{{.album.ID}}">
<p>Title <input type="text" name="title" value="{{.album.Title}}" size="30" placeholder="Input Title"></p>
<p>Artist <input type="text" name="artist" value="{{.album.Artist}}" size="30" placeholder="Input Artist"></p>
<p>Price <input type="text" name="price" value="{{.album.Price}}" size="30" placeholder="Input Price"></p>
<p><input type="submit" value="Send"></p>
</form>
</body>
</html>
使用している教材はこちら↓
おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。