如何在python运行时获得像Jinja这样的嵌套模板。 TBC我的意思是如何从基本模板继承一堆模板,只需在基本模板的块中归档,就像Jinja / django-templates一样。是否可以在标准库中使用html/template
。
如果不可能,我的替代方案是什么。小胡子似乎是一个选项,但我会错过html/template
那些漂亮的微妙特征,如上下文敏感的转义等?还有什么其他选择?
(环境:Google App Engin,Go runtime v1,Dev - Mac OSx lion)
感谢阅读。
答案 0 :(得分:120)
是的,这是可能的。 html.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
地图。
答案 1 :(得分:9)
请注意,当您执行基本模板时,必须将值传递给子模板,在这里我只需传递“。”,以便传递所有内容。
模板一显示{{。}}
{{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)
}
答案 2 :(得分:5)
使用Pongo,这是一套超级Go模板,支持{{extends}}和{{block}}标签进行模板继承,就像Django一样。
答案 3 :(得分:4)
我已经回到这个问题好几天了,最后咬了一口子,为此写了一个小的抽象层/预处理器。它基本上是:
答案 4 :(得分:0)
曾经与其他模板程序包一起工作过,现在有一天我主要使用标准的html / template程序包,我想我很天真地不欣赏它提供的简单性和其他优点。我使用非常相似的方法对接受的答案进行了以下更改
您不需要使用其他base
模板来包装布局,为每个已解析的文件创建一个模板块,因此在这种情况下它是多余的,我也想使用新版本中提供的block操作of 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)