iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
0
Modern Web

BeeGo系列 第 8

Template

本來預期上篇就可以把 CRUD 做完,實際試下去,才知道 bee 這工具不如預期來的好。今天除了簡單的介紹 Template 之外,也順便實作出使用者列表頁面。

基本用法

言歸正傳,BeeGo 的 Template 是直接使用 Go 的 Template 模組,所以語法是一樣的。

當 Controller 裡用

c.Data["Name"] = "John Doe"

要取用變數時,就是用

{{.Name}}

當變數是 list/slice/map 時,可以用 range

<!-- map -->
{{range $key, $val := .object_map}}
    <p>{{$key}}:{{$val}}</p>
{{end}}

<!-- list/slice -->
{{range $object := .object_list}}
  <p>{{$object.Name}}</p>
{{end}}

要做條件式的判斷時,是這樣用:

<!-- 可以用 eq / ne / lt / le / gt / ge -->
{{if eq true .Var1 .Var2 .Var3}}

{{end}}

不過 Go 的 Template 沒辦法像 Django template 或 Jinja2 那麼的彈性,這部份得花點時間去熟悉跟習慣。

套嵌

在 Django 裡,很常用的手法就是使用套嵌,把重複的部份抽取到基礎的模版,然後其他頁面就直接用 {% extends 'base.html' %} 來重複使用。BeeGo 裡則是用 {{ template "base.tpl" . }} ,接下來,就直接看程式碼比較快。

先在 views 下,新增一個 base.tpl (完整程式) ,關鍵的地方在於 {{ block "content" . }}{{ end }} 與 {{ block "scripts" . }}{{ end }} ,這兩個 block 表示要讓含括的頁面去填。這裡要注意一下 '.' ,這個 '.' 記得一定要寫,要不然會引用不到變數。

<!doctype html>
<html lang="en">
  <head>
    <!-- 省略 -->
  </head>
  <body>
    <!-- 省略 -->

<main role="main" class="container">
  <div class="starter">
    {{ block "content" .}}{{end}}
  </div>
</main><!-- /.container -->
                                                                                                                                                                                               
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>           
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>                                                                                                                                                                                 
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>                                                                                                                                                                                    
    {{ block "scripts" .}}{{end}}                                                                                                                                                              
</html>

接著改寫 views/user/index.tpl

{{ template "base.tpl" . }}                                                                                                                                                                    
                                                                                                                                                                                               
{{ define "content" }}                                                                                                                                                                         
  <h1>User list</h1>                                                                                                                                                                           
  {{if eq true .has_error}}                                                                                                                                                                    
  <div class="alert alert-danger" role="alert">                                                                                                                                                
    Error: {{.error}}                                                                                                                                                                          
  </div>                                                                                                                                                                                       
  {{end}}                                                                                                                                                                                      
                                                                                                                                                                                               
  <p>Total records: {{.object_list_len}}</p>                                                                                                                                                   
  <table class="table">                                                                                                                                                                        
    <thead>                                                                                                                                                                                    
      <th scope="col">#</th>                                                                                                                                                                   
      <th scope="col">Name</th>                                                                                                                                                                
      <th scope="col">Gender</th>                                                                                                                                                              
      <th scope="col">Birthday</th>                                                                                                                                                            
    </thead>                                                                                                                                                                                   
    <tbody>                                                                                                                                                                                    
    {{range $object := .object_list}}                                                                                                                                                          
      <tr>                                                                                                                                                                                     
        <th scope="row">{{$object.Id}}</th>                                                                                                                                                    
        <td>{{$object.Name}}</td>                                                                                                                                                              
        <td>{{$object.Gender}}</td>                                                                                                                                                            
        <td>{{date $object.Birthday "Y-m-d"}}</td>                                                                                                                                             
      </tr>                                                                                                                                                                                    
    {{end}}                                                                                                                                                                                    
  </table>                                                                                                                                                                                     
{{ end }}                                                                                                                                                                                      
                                                                                                                                                                                               
{{ define "scripts" }}                                                                                                                                                                         
{{ end }}

這邊主要看幾個點:

  1. {{ template "base.tpl" . }} 表示含括 base.tpl,一樣,後面的 '.' 不可省略,因為少了這個 '.' ,變數就引用不到。
  2. {{ define "content" }} {{ end }} 則是填要放的內容。

Controller

View 的部份已經寫好了,現在還少一個 Controller 來處理顯示的邏輯。所以接下來直接複製之前產生的 controllers/user.go 來產生一個新的 controller

cp controllers/user.go controllers/myuser.go

接著做以下更動:

  1. 除了 GetAll() 以外的函式都刪除掉。
  2. 將 UserController 改名為 MyUserController
  3. GetAll() 裡移除掉 c.Data["json"] 以及 c.ServeJSON()

下方只保留關鍵的部份,完整程式在 github

package controllers

import (
	"errors"
	"my/hello/models"
	"strings"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
)

//  UserController operations for User
type MyUserController struct {
	beego.Controller
}

// 省略
func (c *MyUserController) GetAll() {
  // 省略
	// query: k:v,k:v
	if v := c.GetString("query"); v != "" {
		for _, cond := range strings.Split(v, ",") {
			kv := strings.SplitN(cond, ":", 2)
			if len(kv) != 2 {
				c.Data["has_error"] = true
				c.Data["error"] = errors.New("Error: invalid query key/value pair")
				return
			}
			k, v := kv[0], kv[1]
			query[k] = v
		}
	}

	logs.Debug("get all users")
	l, err := models.GetAllUser(query, fields, sortby, order, offset, limit)
	if err != nil {
		logs.Error(err.Error())
		c.Data["has_error"] = true
		c.Data["error"] = err.Error()
	} else {
		logs.Debug("len(l)=", len(l))
		c.Data["object_list_len"] = len(l)
		c.Data["object_list"] = l
	}
  // 指定 Template
	c.TplName = "user/index.tpl"
}

Router

最後,就是在路由裡增加我們新增的 MyUserController

package routers

import (
	"my/hello/controllers"

	"github.com/astaxie/beego"
)

func init() {
	beego.Router("/", &controllers.MainController{})
	beego.Router("/about", &controllers.AboutController{})

  // 表示將 GET /myuser/ 指向 MyUserController 的 GetAll()
	beego.Router("/myuser", &controllers.MyUserController{}, "get:GetAll")
}

至此,完成使用者列表的頁面。

參考資料


上一篇
Controller and View(2)
下一篇
Form and CSRF(1)
系列文
BeeGo30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言