DEV Community

SKY-HaYaTo
SKY-HaYaTo

Posted on • Edited on

How to insert and update Data Golang Web App with Beego?

Introduction

Beegois a web application framework made from base on Golang,and this is often used as large development projects.
You know that there are some web frameworks using golang like Gin,Echo,revel,Beego and iris,and many apps are releasing today.
In personal development, I choose Beego because of a simple architechture.
The framework is accepted as MVC model which is suitable to develop huge project web applications.
In addition,Making Beego project is very simple, only one command to produce project.
In this article, I am developing TaskApp including to update data using PostgreSQL.

Derectory of In may Beego project.

My project directory as below.
M(Model): Model classes.
V(Views):View classs including template engine.
C(Controllers):Controller class.

MY-FIRST-BEEGO-PROJECT
├─ conf
│  └─ app.conf
├─ controllers
│  └─ default.go
├─ crypt
│  └─ crypt.go
├─ models
│  └─ todo.go
├─ routers
│  └─ router.go
└─ static
   ├─ css
   ├─ img
   ├─ js
   │  ├─ form.js
   │  ├─ login.js
   │  ├─ reload.min.js
   │  ├─ todoCreate.js
   │  ├─ todoCard.js
   │  └─ todoList.js
   ├─ lib
   │  └─ bootstrap
   │     ├─ css
   │     │  ├─ bootstrap-grid.min.css
   │     │  └─ bootstrap.min.css
   │     ├─ js
   │     │  ├─ bootstrap-bundle.min.js
   │     │  └─ bootstrap.min.js
   │     ├─ jquery
   │     │  └─ jquery.js
   │     └─ upload
   ├─ views
   │  ├─ mytodo
   │  │  ├─ addTodo.tpl
   │  │  └─ myList.tpl
   │  ├─ index.tpl
   │  ├─ subIndex.tpl
   │  └─ thirdIndex.tpl
   └─ main.go

Enter fullscreen mode Exit fullscreen mode

Make Frontend Page

Firstry,I make frontend page using templatenengine .tpl.
If you want to update data,like making form and send using POST method.

views/myTodo/myTodoEdit.tpl

<!DOCTYPE html>
<html>
    <head>
        <title>Todo編集</title>
        <!--共通-->
        <link rel="stylesheet" type="text/css" href="/static/lib/bootstrap/css/bootstrap.min.css"/>
        <script type="text/javascript" src="/static/lib/jquery/jquery.js"></script>
        <!--個別-->
        <script type="text/javascript" src="/static/js/taskEdit.js"></script>
    </head>
    <body>
        <form enctype="multipart/form-data">
            <div>
                <input type="hidden" id="registerId" name="registerId" value=""/>
                <input type="hidden" id="taskId" name="taskId" value=""/>                
            </div>
            <div class="form-group mb-3">
                <label>タスク名</label>
                <input type="text" id="myTask" name="myTask" class="form-control border border-dark" value="" required />
            </div>
            <div class="form-group mb-3">
                <label>タスク詳細</label>
                <textarea class="form-control" id="myTaskDescription" name="myTaskDescription" rows="3"></textarea>
            </div>
            <div class="form-group mb-3">
                <label>優先度</label>
                <select id="myTaskPriority" name="myTaskPriority" class="form-select form-select-lg mb-3" aria-label=".form-select-lg">
                    <option>-- 選択してください --</option>
                    <option value="1">高</option>
                    <option value="2">中</option>
                    <option value="3">低</option>
                </select>
            </div>
            <div class="form-group mb-2">
                <label>タスク画像</label>
                <input type="file" id="myTaskImage" name="myTaskImage" class="form-control border border-dark" />
            </div>
            <div class="form-group mb-2" class="btn btn-primary">
                <button id="todoEdit" class="btn btn-primary" type="button">
                    更新
                </button>
                <button id="backToTopPage" class="btn btn-secondary" type="button">
                    一覧に戻る
                </button>
            </div>
        </form>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Sending Formdata to server using HTTP method POST.

static/js/todoEdit.js

$(document).ready(function(){
    //SessionStorageからユーザIDを取得する
    const userId = sessionStorage.getItem("userId");

    //一覧画面に戻るボタンを押下した時の処理
    $('#backToTopPage').on('click',function(){
        location.replace(`/sub?userid=${userId}`);
    });

    /**
     * ---------------------------------------
     * URLクエリパラメータからタスクIDを取得する
     * ---------------------------------------
     */
    // URLのクエリ文字列を取得する
    const queryString = window.location.search;
    // URLSearchParamsオブジェクトを作成してクエリ文字列を解析する
    const param = new URLSearchParams(queryString);
    // 特定のパラメータの値を取得する
    document.getElementById("taskId").value = param.get("taskId");
    //タスクIDを変数に格納する
    const taskId = param.get("taskId");

    $.ajax({
        url:`/controllers/selectEditTodo?taskid=${taskId}`,
        method:'GET',
        success:function(response){
            console.log(response);
            const registerId = document.getElementById("registerId");
            registerId.value = response[0].Register.Id;

            //編集対象のタスクを取得したら編集画面に詰める。
            const taskId = document.getElementById("taskId");
            taskId.value = response[0].TaskId;

            const taskName = document.getElementById("myTask");
            taskName.value =response[0].TaskName;

            const taskDescription = document.getElementById("myTaskDescription");
            taskDescription.value = response[0].TaskDescription;

            const taskPriority = document.getElementById("myTaskPriority");
            if(response[0].TaskPriority === "1"){
                taskPriority.options[1].selected = true;
            }

            if(response[0].TaskPriority === "2"){
                taskPriority.options[2].selected = true;
            }

            if(response[0].TaskPriority === "3"){
                taskPriority.options[3].selected = true;
            }

        },
        error:function(response){
            console.log(response);
            alert('データを取得できませんでした。');
        }
    });

    //更新ボタン押下時の処理
    $('#todoEdit').on('click',function(e){
        //デフォルトのイベントを防止する処理
        e.preventDefault();

        //フォームデータを作成する
        let formData = new FormData();
        formData.append("registerId",$('#registerId').val());
        formData.append("taskId",$("#taskId").val());
        formData.append("taskName",$('#myTask').val());
        formData.append("taskDescription",$('#myTaskDescription').val());
        formData.append("taskpriority",$('#myTaskPriority').val());
        formData.append("taskImage",$('#myTaskImage')[0].files[0]);

        $.ajax({
            url:"/controllers/updateTask",
            method:"POST",
            data:formData,
            processData:false,
            contentType:false,
            success:function(response){
                console.log(response);
            },
            error:function(response){
                alert("Update is success.");
                console.log(response);
            }
        });
    });
});
Enter fullscreen mode Exit fullscreen mode

Make Backend

Data sent from frontend, is processed by server using golang.

I make Controller class in default.go class.
In Beego, Controller class is make as below.
First, we need to write struct , and then make process you want to.

controllers/default.go

type TodoUpdateController struct {
    beego.Controller
}

func (c *TodoUpdateController) Post() {
    // Accept from Screen data
    registerId := c.GetString("registerId")
    taskId := c.GetString("taskId")
    taskName := c.GetString("taskName")
    taskDescription := c.GetString("taskDescription")
    taskPriority := c.GetString("taskpriority")

    fmt.Println("RegisterId which is accepted from Browser, is ", registerId)
    fmt.Println("TaskId which is accepted from Browser, is", taskId)
    fmt.Println("TaskName which is accepted from Browser, is ", taskName)
    fmt.Println("TaskDescription which is accepted from Browser", taskDescription)
    fmt.Println("TaskPriority which is accepted from browser,is ", taskPriority)

    //Upload a file which is accepted from browser
    f, h, err := c.GetFile("taskImage")
    if err != nil {
        fmt.Println("File error", err)
        c.Ctx.ResponseWriter.WriteHeader(500)
        c.Ctx.WriteString("Try to upload a files is Failed.")
        return
    }
    defer f.Close()

    //Decition of storage file path
    uploadPath := "static/upload"
    err = os.MkdirAll(uploadPath, os.ModePerm)

    if err != nil {
        fmt.Println("Try to save a file is Failed", err)
        c.Ctx.ResponseWriter.WriteHeader(500)
        c.Ctx.WriteString("Fail to save a file.")
        return
    }

    //Save taskImage after getting image
    fileName := h.Filename
    savepath := filepath.Join(uploadPath, fileName)

    //Save taskImage after getting image
    outFile, err := os.Create(savepath)

    if err != nil {
        fmt.Println("ファイル保存エラー", err)
        c.Ctx.ResponseWriter.WriteHeader(500)
        c.Ctx.WriteString("fail to save a file")
        return
    }

    defer outFile.Close()

    _, err = outFile.ReadFrom(f)
    if err != nil {
        fmt.Println("fail to write to a File")
        c.Ctx.ResponseWriter.WriteHeader(500)
        c.Ctx.WriteString("Fails to write to a file.")
        return
    }

    //Debug program]
    fmt.Println("Saved a file name is ", fileName)

    //Generate Instance of Orm
    o := orm.NewOrm()

    //Generate Instance of Task
    var updateTask models.Task
    //Initialize Register Model
    updateTask.Register = &models.Register{}

    //Begin Transactions
    tx, err := o.Begin()
    numTaskId, _ := strconv.ParseInt(taskId, 10, 64)
    numRegisterId, _ := strconv.ParseInt(registerId, 10, 64)

    updateTask.TaskId = numTaskId
    updateTask.TaskName = taskName
    updateTask.TaskDescription = taskDescription
    updateTask.TaskPriority = taskPriority
    updateTask.TaskImage = "http://localhost:8080/static/upload/" + fileName
    updateTask.Register.Id = numRegisterId

    _, err = tx.Update(&updateTask)

    if err != nil {
        tx.Rollback()
        fmt.Println("Error Exception was started.")
        c.Data["json"] = map[string]string{
            "status":  "Fail to Insert.",
            "message": "Fail to insert updated Task Information.",
        }
        c.ServeJSON()
        return
    }

    err = tx.Commit()

    if err != nil {
        fmt.Println("Fail to TransactionCommit.")
        c.Data["json"] = map[string]string{
            "status":  "fail to Transaction",
            "message": "Fail to Transaction(Insert)",
        }
        c.ServeJSON()
        return
    }

    c.Ctx.ResponseWriter.WriteHeader(500)
    c.Ctx.WriteString("Success to update task.")
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)