読者です 読者をやめる 読者になる 読者になる

peketaminの日記

その辺のプログラマーのチラ裏です。

golang: Django, Jinja like Template inheritance using "html/template" and how to unescape HTML in "html/template"

(Japanese version: here)

Code

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: "How do I search google Go pages?",
        Body:  "Use <b>Golang</b> instead of <i>Go</i>.",
    }
    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

Open http://localhost:8080 in a browser.

Points

  • Registering custom template methods using template.FuncMap{} and template.Funcs().
    Custom method is used in template/view.html at {{.Body|safehtml}}
  • Reading a child template like below:
    go template.ParseFiles("templates/base.html", "templates/view.html")
  • Set only "base" scope like below:
    go templates.ExecuteTemplate(w, "base", dat)

Note

var := template.HTML(var) in Go can be used like a Django's method var = mark_safe(var).

I could use template.HTML() but it was hard to convert type when ORM library save models. Then I want a method like a Django and Jinja's {{var|safe}} that can be used at a time to display raw HTML code.

By the way, We can disable autoescape mode as default using text/template instead of html/template. While using it, we can escape code with html.EscapeString() as needed. But it's not secure as way of thinking on safety engineering.


Reference: