94

如何在 python 运行时获得像 Jinja 这样的嵌套模板。TBC 我的意思是我如何让一堆模板继承自基本模板,只需归档基本模板的块,就像 Jinja/django-templates 一样。是否可以仅html/template在标准库中使用。

如果这不可能,我的选择是什么。胡子似乎是一种选择,但我会错过那些微妙的功能,html/template比如上下文敏感的转义等吗?还有哪些其他选择?

(环境:Google App Engin、Go runtime v1、Dev - Mac OSx lion)

谢谢阅读。

4

5 回答 5

142

是的,有可能。Ahtml.Template实际上是一组模板文件。如果您执行此集中定义的块,则它可以访问此集中定义的所有其他块。

如果您自己创建此类模板集的地图,您将拥有与 Jinja / Django 提供的基本相同的灵活性。唯一的区别是html/template包不能直接访问文件系统,所以你必须自己解析和组合模板。

考虑以下示例,其中两个不同的页面(“index.html”和“other.html”)都继承自“base.html”:

// Content of base.html:
{{define "base"}}<html>
  <head>{{template "head" .}}</head>
  <body>{{template "body" .}}</body>
</html>{{end}}

// Content of index.html:
{{define "head"}}<title>index</title>{{end}}
{{define "body"}}index{{end}}

// Content of other.html:
{{define "head"}}<title>other</title>{{end}}
{{define "body"}}other{{end}}

以及以下模板集地图:

tmpl := make(map[string]*template.Template)
tmpl["index.html"] = template.Must(template.ParseFiles("index.html", "base.html"))
tmpl["other.html"] = template.Must(template.ParseFiles("other.html", "base.html"))

您现在可以通过调用呈现您的“index.html”页面

tmpl["index.html"].Execute("base", data)

你可以通过调用呈现你的“other.html”页面

tmpl["other.html"].Execute("base", data)

通过一些技巧(例如,模板文件的一致命名约定),甚至可以tmpl自动生成地图。

于 2012-07-13T09:53:00.510 回答
14

请注意,当您执行基本模板时,您必须将值传递给子模板,这里我只是传递“.”,以便将所有内容传递下去。

模板一显示 {{.}}

{{define "base"}}
<html>
        <div class="container">
            {{.}}
            {{template "content" .}}
        </div>
    </body>
</html>
{{end}}

模板二显示传递给父级的 {{.domains}}。

{{define "content"}}
{{.domains}}
{{end}}

请注意,如果我们使用 {{template "content" .}} 而不是 {{template "content" .}},则无法从内容模板访问 .domains。

DomainsData := make(map[string]interface{})
    DomainsData["domains"] = domains.Domains
    if err := groupsTemplate.ExecuteTemplate(w, "base", DomainsData); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
于 2016-06-30T01:57:11.970 回答
6

使用过其他模板包,现在我主要使用标准 html/模板包,我想我很天真,没有欣赏它提供的简单性和其他好东西。我使用非常相似的方法来接受以下更改

你不需要用额外base的模板包装你的布局,为每个解析的文件创建一个模板块,所以在这种情况下它是多余的,我也喜欢使用新版本的 go 中提供的块操作,它允许你有默认阻止内容,以防您未在子模板中提供

// base.html
<head>{{block "head" .}} Default Title {{end}}</head>
<body>{{block "body" .}} default body {{end}}</body>

您的页面模板可以与

// Content of index.html:
{{define "head"}}<title>index</title>{{end}}
{{define "body"}}index{{end}}

// Content of other.html:
{{define "head"}}<title>other</title>{{end}}
{{define "body"}}other{{end}}

现在执行你需要这样调用它的模板

tmpl["index.html"].ExecuteTemplate(os.Stdout, "base.html", data)
于 2018-10-25T19:38:43.243 回答
5

使用Pongo,它是 Go 模板的超集,支持 {{extends}} 和 {{block}} 标签进行模板继承,就像 Django 一样。

于 2013-04-02T13:28:38.020 回答
5

几天来我一直在回到这个答案,终于硬着头皮为此写了一个小的抽象层/预处理器。它基本上:

  • 将“扩展”关键字添加到模板。
  • 允许覆盖“定义”调用(因此可以使用 greggory 的默认值)
  • 允许未定义的“模板”调用,它们只给出一个空字符串
  • 设置的默认值。在“模板”中调用 . 父母的

https://github.com/daemonl/go_sweetpl

于 2014-02-03T07:13:58.003 回答