LoginSignup
60
50

More than 5 years have passed since last update.

golang で html/template でのテンプレートの継承と、HTML エスケープしないで変数を出力する方法 (Django, Jinja みたいに)

Last updated at Posted at 2014-08-03

コード

template/base.html

{{define "base"}}<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>{{template "title" .}}</title>
    </head>

    <body>
        <div class="content">
            {{template "body" .}}
        </div><!-- /.content -->
    </body>
</html>{{end}}

template/view.html

{{define "title"}}{{.Title}}{{end}}

{{define "body"}}
<h1>{{.Title}}</h1>
<article>
    {{.Body|safehtml}}
</article>
{{end}}

templatetest.go

package main

import (
    "html/template"
    "net/http"
)

func viewHandler(w http.ResponseWriter, r *http.Request) {
    funcMap := template.FuncMap{
        "safehtml": func(text string) template.HTML { return template.HTML(text) },
    }
    templates := template.Must(template.New("").Funcs(funcMap).ParseFiles("templates/base.html",
        "templates/view.html"))
    dat := struct {
        Title string
        Body  string
    }{
        Title: "メイジェイって",
        Body:  "いっつも<b>ありのまま</b>だよね",
    }
    err := templates.ExecuteTemplate(w, "base", dat)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func main() {
    http.HandleFunc("/", viewHandler)
    http.ListenAndServe(":8080", nil)
}
go run templatetest.go

して ブラウザで http://localhost:8080 を開く。

ポイント

  • template.FuncMap{}template.Funcs() でテンプレート中で使える独自メソッドをテンプレート側に登録しているところ。 template/view.html{{.Body|safehtml}} で使ってる
  • ネスト対象の子テンプレートを

    template.ParseFiles("templates/base.html", "templates/view.html")
    

    で読み込んでいるところ。

  • templates.ExecuteTemplate(w, "base", dat)
    

    で、一番大きな範囲の base だけを明示的に指定しているところ。

メモ

Go では var := template.HTML(var) することで、
Django での var = mark_safe(var) みたいなことが出来る。

ただ、このままだと、
例えば DB に保存する場合に型の違いを処理しないといけなかったりして、
そうじゃなくて、出力時だけ生で出力する、
Django や Jinja2 での {{var|safe}}
みたいな仕組みが欲しかった。

ちなみに html/template じゃなくて text/template を使うと自動エスケープを気にしなくて良くなる感じだった。この場合、必要なところだけ html.EscapeString() でエスケープ出来るが、せっかく安全側に倒してくれる仕組みを言語のほうで用意してくれているので、そっちの恩恵にあずかりたかった。


下記を参考にさせて頂いた。

ちなみに html - GoDoc を見ると func UnescapeString(s string) string なんてものもあるみたい。

60
50
0

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
  3. You can use dark theme
What you can do with signing up
60
50