Go Lang and PostgreSQL Web App MVC Pattern Part 6

Have a Database Problem? Speak with an Expert for Free
Get Started >>

Introduction

This is part six of a multipart tutorial series explaining how to create a Go Lang and PostgreSQL Web App with MVC pattern. The previous section of this tutorial series covered how to execute an INSERT operation of a single record in PostgreSQL. Part six will now explain how to update a single record and display that newly updated record for review.

Prerequisite

  • Have a solid understanding of the first five parts of this Go Lang and PostgreSQL Web App with MVC pattern tutorial series.

Update a Record in PostgreSQL using Go Lang

The previous section of this series explained how to insert a record in the PostgreSQL database. Similar to what was covered in the previous part of this series, the main.go file must be update by creating new functions for the http.HandleFunc() method as follows:

1
2
3
4
5
6
7
8
9
10
11
http.HandleFunc("/", index)
http.HandleFunc("/list", model.PatientIndex)
http.HandleFunc("/patient/show", model.PatientShow)
http.HandleFunc("/patient/create", model.PatientCreate)
http.HandleFunc("/patient/create/process", model.PatientCreateProcess)
// below are the newly added code(s)
http.HandleFunc("/patient/update", model.PatientUpdate)
http.HandleFunc("/patient/update/process", model.UpdateProcess)
// end of of newly added code(s)

http.ListenAndServe(":8080", nil)
  • Two lines of scripts were added to handle the editing of the patient’s details via form http.HandleFunc("/patient/update", model.PatientUpdate). This is the actual updating process of the record from the form values http.HandleFunc("/patient/update/process", model.UpdateProcess)

Controller for Updating a Record in PostgreSQL using Go Lang

  • As in previous parts of this tutorial series, the controller for the new request handlers must be created. Create the new function in the handler.go file against the handler http.HandleFunc(“/patient/update”, model.PatientUpdate)` with the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func PatientUpdate(w http.ResponseWriter, r *http.Request) {
    if r.Method != "GET" {
        http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed)
        return
    }

    patient, err := SinglePatient(r)
    switch {
    case err == sql.ErrNoRows:
        http.NotFound(w, r)
        return
    case err != nil:
        http.Error(w, http.StatusText(500), http.StatusInternalServerError)
        return
    }

    config.TPL.ExecuteTemplate(w, "updatePatient.gohtml", patient)
}

Here is breakdown of the above code:

  • The code will call a function from the models.go SinglePatient(r) and the results will be stored within the variable patient.
  • As will be discussed in the following section, that variable is then passed to the template updatePatient.gohtml for a further process.

With the controller properly set up, the user can make changes to a selected record.

  • Next, the controller that will bridge the front-end and the model for applying the changes will be created. Execute the following code to create a function for updating the record, naming it PatientUpdateProcess():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func PatientUpdateProcess(w http.ResponseWriter, r *http.Request) {
    if r.Method != "POST" {
        http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed)
        return
    }

    patient, err := UpdatePatient(r)
    if err != nil {
        http.Error(w, http.StatusText(406), http.StatusBadRequest)
        return
    }

    config.TPL.ExecuteTemplate(w, "updatedPatient.gohtml", patient)
}
  • The above code will call up a function named UpdatePatient(r) that resides in the models.go file. The results from this operation will be stored in the variable patient. The variable patient will be forwarded to the template updatedPatient.gohtml for further processing.

NOTE: The index.gohtml code must be updated with the following command to trigger the handler created in the prevous sections: -td--a class="action" href="/patient/show?id={{.Patient_id}}-View-/a--/td-

Configuring Model for Updating a Record in PostgreSQL using Go Lang

This section will cover how to create the model or business logic against the controllers that were created earlier. The models.go file will be updated to reflect the functions, as needed.

Referring back to the first function, the (SinglePatient(r)) as required by the controller already exists in the application. The method for executing this function may be reviewed in part four of this tutorial series.

The code for creating the second function named PatientUpdateProcess(r), as required by the application controller, follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func UpdatePatient(r *http.Request) (Patient, error) {
    // get form values
    p := Patient{}
    p.Patient_id = r.FormValue("patientID")
    p.Name = r.FormValue("name")
    p.Lastname = r.FormValue("lastname")
    p.Gender = r.FormValue("gender")
    // converst the string value to integer
    pID := r.FormValue("age")
    age, err := strconv.Atoi(pID)
    p.Age = age
    // validate form values
    if p.Patient_id == "" || p.Name == "" || p.Lastname == "" || p.Gender == "" || pID == "" {
        return p, errors.New("400. Bad request. All fields must be complete.")
    }

    // insert values
    _, err = config.DB.Exec("UPDATE tbl_patientinfo SET patient_id = $1, name=$2, lastname=$3, gender=$4, age=$5 WHERE patient_id=$1;", p.Patient_id, p.Name, p.Lastname, p.Gender, p.Age)
    if err != nil {
        return p, err
    }
    return p, nil
}

Note that the above code was almost identical to the code used in performing the INSERT operation. A breakdown of the code follows:

  • The code gets and assigns the form values to the Patient slice.
  • A basic validation is performed.
  • The UPDATE operation is preformed using the config.DB.Exec() method.
  • Finally, the value of the slice, being p, is returned and processed as needed.

Configuring the front-end

The front-end templates, as described in the previous parts of this tutorial series, will now be created.

  • First, the form where the user can make changes on a particular patients record will be created and named updatePatient.gohtml. Create the new file within the templates directory and append it with the following HTML structure:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!DOCTYPE html>

    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Edit Patient Details</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    </head>
    <body>
        <!--[if lt IE 7]>
           <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
       <![endif]-->


<div class="container mt-4" >
<h1>Edit Patient</h1>

<form method="post" action="/patient/update/process">
  <div class="form-group">
    <label for="patienID">Patient ID</label>
    <input type="text" class="form-control" name="patientID" id="patientID" placeholder="Patient ID" value="{{.Patient_id}}">
  </div>
  <div class="form-group">
    <label for="name">Patient's Name</label>
    <input type="text" class="form-control" name="name" id="name" placeholder="Patient's Name" value="{{.Name}}">
  </div>
  <div class="form-group">
    <label for="name">Patient's LastName</label>
    <input type="text" class="form-control" name="lastname" id="lastname" placeholder="Patient's LastName" value="{{.Lastname}}">
  </div>
  <div class="form-group">
    <label for="name">Patient's Gender</label>
    <input type="text" class="form-control" name="gender" id="gender" placeholder="Patient's Gender" value="{{.Gender}}">
  </div>
  <div class="form-group">
    <label for="name">Patient's Age</label>
    <input type="text" class="form-control" name="age" id="age" placeholder="Patient's Age" value="{{.Age}}">
  </div>
  <input class="btn btn-primary" type="submit">
  <a class="action btn btn-primary" href="/">Cancel</a>
</form>
</div>
        <script src="" async defer></script>
    </body>
</html>

The above code will display the details of the selected patient.

The above structure should resemble the following:

  • Next, a template will be created that will display the updated record for review purposes. To achieve this, execute the following code to create a new file in the templates directory and name it updatedPatient.gohtml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Updated Patient Information</title>
    <link
     rel="stylesheet"
     href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
     integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
     crossorigin="anonymous"
   />
    <script
     src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
     integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
     crossorigin="anonymous"
   ></script>
  </head>
  <body>
    <div class="container mb-6">
      <form class="mt-5">
        <h2>Patient's Updated Information</h2>
        <div class="form-group row">
          <label for="name" class="col-sm-2 col-form-label">Name</label>
          <div class="col-sm-10">
            <input
             type="text"
             class="form-control"
             id="name"
             value="{{.Name}} {{.Lastname}}"
             disabled
           />
          </div>
        </div>
        <div class="form-group row">
          <label for="gender" class="col-sm-2 col-form-label">Gender</label>
          <div class="col-sm-10">
            <input
             type="text"
             class="form-control"
             id="gender"
             value="{{.Gender}}"
             disabled
           />
          </div>
        </div>
        <div class="form-group row">
          <label for="age" class="col-sm-2 col-form-label">Age</label>
          <div class="col-sm-10">
            <input
             type="text"
             class="form-control"
             id="age"
             value="{{.Age}}"
             disabled
           />
          </div>
        </div>

        <div class="form-group row">
          <div class="col-sm-10 offset-sm-2">
            <a class="btn btn-primary" href="/"> « Patient Listing</a>
          </div>
        </div>
      </form>
    </div>
  </body>
</html>
  • The necessary files for our UPDATE operation have now been created. Now test the application by executing following three steps in sequence:

  • First, run the following command in the projects directory: go run main.go.

  • Second, navigate to the project using the URL: localhost:8080/list.
  • Third, perform the update operation.

Conclusion

This was part six of a multipart tutorial series explaining how to create a Go Lang and PostgreSQL Web App with MVC pattern. Part six covered how to perform an UPDATE operation against a selected PostgreSQL record and display that newly updated record for review. This section specifically explained how to set up the controller to make changes to a selected record, how to configure the front-end templates to display the updated record for review and test the application. Part six also provided a step-by-step breakdown of the code used to execute these function. It is important to remember that the main.go file must always be update by creating new functions for the http.HandleFunc() method in order for the INSERT operation to function properly.

The Code

Below is the code of the files that we used in this application.

The main.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
    "html/template"
    "net/http"
    "patientinfo/model"

    _ "github.com/lib/pq"
)

// package level scope, which means it can be accessed anywhere in this packager.
var tpl *template.Template

func main() {
http.HandleFunc("/", index)
http.HandleFunc("/list", model.PatientIndex)
http.HandleFunc("/patient/show", model.PatientShow)
http.HandleFunc("/patient/create", model.PatientCreate)
http.HandleFunc("/patient/create/process", model.PatientCreateProcess)
// below are the newly added code(s)
http.HandleFunc("/patient/update", model.PatientUpdate)
http.HandleFunc("/patient/update/process", model.UpdateProcess)
// end of of newly added code(s)

http.ListenAndServe(":8080", nil)
}

func index(w http.ResponseWriter, r *http.Request) {
    http.Redirect(w, r, "/list", http.StatusSeeOther)
}

The updatePatient.gohtml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!DOCTYPE html>

    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Edit Patient Details</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    </head>
    <body>
        <!--[if lt IE 7]>
           <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
       <![endif]-->


<div class="container mt-4" >
<h1>Edit Patient</h1>

<form method="post" action="/patient/update/process">
  <div class="form-group">
    <label for="patienID">Patient ID</label>
    <input type="text" class="form-control" name="patientID" id="patientID" placeholder="Patient ID" value="{{.Patient_id}}">
  </div>
  <div class="form-group">
    <label for="name">Patient's Name</label>
    <input type="text" class="form-control" name="name" id="name" placeholder="Patient's Name" value="{{.Name}}">
  </div>
  <div class="form-group">
    <label for="name">Patient's LastName</label>
    <input type="text" class="form-control" name="lastname" id="lastname" placeholder="Patient's LastName" value="{{.Lastname}}">
  </div>
  <div class="form-group">
    <label for="name">Patient's Gender</label>
    <input type="text" class="form-control" name="gender" id="gender" placeholder="Patient's Gender" value="{{.Gender}}">
  </div>
  <div class="form-group">
    <label for="name">Patient's Age</label>
    <input type="text" class="form-control" name="age" id="age" placeholder="Patient's Age" value="{{.Age}}">
  </div>
  <input class="btn btn-primary" type="submit">
  <a class="action btn btn-primary" href="/">Cancel</a>
</form>
</div>
        <script src="" async defer></script>
    </body>
</html>

The updatedPatient.gohtml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Updated Patient Information</title>
    <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
      integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
      crossorigin="anonymous"
    />
    <script
      src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
      integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <div class="container mb-6">
      <form class="mt-5">
        <h2>Patient's Updated Information</h2>
        <div class="form-group row">
          <label for="name" class="col-sm-2 col-form-label">Name</label>
          <div class="col-sm-10">
            <input
              type="text"
              class="form-control"
              id="name"
              value="{{.Name}} {{.Lastname}}"
              disabled
            />
          </div>
        </div>
        <div class="form-group row">
          <label for="gender" class="col-sm-2 col-form-label">Gender</label>
          <div class="col-sm-10">
            <input
              type="text"
              class="form-control"
              id="gender"
              value="{{.Gender}}"
              disabled
            />
          </div>
        </div>
        <div class="form-group row">
          <label for="age" class="col-sm-2 col-form-label">Age</label>
          <div class="col-sm-10">
            <input
              type="text"
              class="form-control"
              id="age"
              value="{{.Age}}"
              disabled
            />
          </div>
        </div>

        <div class="form-group row">
          <div class="col-sm-10 offset-sm-2">
            <a class="btn btn-primary" href="/"> « Patient Listing</a>
          </div>
        </div>
      </form>
    </div>
  </body>
</html>

The models.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func UpdatePatient(r *http.Request) (Patient, error) {
    // get form values
    p := Patient{}
    p.Patient_id = r.FormValue("patientID")
    p.Name = r.FormValue("name")
    p.Lastname = r.FormValue("lastname")
    p.Gender = r.FormValue("gender")
    pID := r.FormValue("age")
    age, err := strconv.Atoi(pID)
    p.Age = age
    // validate form values
    if p.Patient_id == "" || p.Name == "" || p.Lastname == "" || p.Gender == "" || pID == "" {
        return p, errors.New("400. Bad request. All fields must be complete.")
    }

    // insert values
    _, err = config.DB.Exec("UPDATE tbl_patientinfo SET patient_id = $1, name=$2, lastname=$3, gender=$4, age=$5 WHERE patient_id=$1;", p.Patient_id, p.Name, p.Lastname, p.Gender, p.Age)
    if err != nil {
        return p, err
    }
    return p, nil
}

The handler.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
func PatientUpdate(w http.ResponseWriter, r *http.Request) {
    if r.Method != "GET" {
        http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed)
        return
    }

    patient, err := SinglePatient(r)
    switch {
    case err == sql.ErrNoRows:
        http.NotFound(w, r)
        return
    case err != nil:
        http.Error(w, http.StatusText(500), http.StatusInternalServerError)
        return
    }

    config.TPL.ExecuteTemplate(w, "updatePatient.gohtml", patient)
}

func PatientUpdateProcess(w http.ResponseWriter, r *http.Request) {
    if r.Method != "POST" {
        http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed)
        return
    }

    patient, err := UpdatePatient(r)
    if err != nil {
        http.Error(w, http.StatusText(406), http.StatusBadRequest)
        return
    }

    config.TPL.ExecuteTemplate(w, "updatedPatient.gohtml", patient)
}

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.