LoginSignup
0

More than 1 year has passed since last update.

【#46 エンジニア転職学習】GinTutorialのWebApp改造 HTMLに連動させる

Posted at

はじめに

富山県に住んでいる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>
使用している教材はこちら↓

おわりに

最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0