在Go语言中使用标准库可以嵌套模板吗?

bwitn5fc  于 2022-12-07  发布在  Go
关注(0)|答案(5)|浏览(193)

我如何获得像Jinja在python运行时中的嵌套模板。TBC我的意思是我如何从一个基本模板继承一堆模板,只是在基本模板的块中归档,就像Jinja/django-templates所做的那样。在标准库中只使用html/template是可能的吗?
如果这不是一种可能性,那么我的替代方案是什么呢?胡子似乎是一种选择,但我会错过html/template的那些微妙的特性吗?比如上下文敏感的转义等等?还有什么其他的替代方案呢?
(环境:Google应用引擎、Go运行时v1、开发人员- Mac OS x lion)
感谢阅读。

8iwquhpp

8iwquhpp1#

是的,这是可能的。一个html.Template实际上是一组模板文件。如果你执行这个集合中的一个定义块,它就可以访问这个集合中定义的所有其他块。
如果你自己创建一个这样的模板集合的Map,你基本上拥有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}}

和以下模板集的Map:

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"))

您现在可以通过调用

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

并且可以通过调用

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

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

n9vozmp4

n9vozmp42#

注意,当你执行你的基模板时,你必须把值传递给子模板,这里我只是简单地传递“.",这样所有的东西都被传递下去了。
模板一显示{{.}}

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

模板2显示传入父模板的{{.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)
    }
qvtsj1bj

qvtsj1bj3#

我曾经使用过其他的模板包,现在我主要使用标准的html/template包,我想我太天真了,没有意识到它提供的简单性和其他好处。
你不需要用额外的base模板 Package 你的布局,模板块是为每个解析的文件创建的,所以在这种情况下它是多余的,我还喜欢使用新版本的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)
nwlqm0z1

nwlqm0z14#

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

thtygnil

thtygnil5#

几天来,我一直在考虑这个问题,最后终于咬紧牙关,为此写了一个小的抽象层/预处理器。它基本上是:

  • 将“extends”关键字添加到模板。
  • 允许覆盖'define'调用(因此可以使用greggory的默认值)
  • 允许未定义的'template'调用,它们只给予一个空字符串
  • 将'template'呼叫中.的预设值设定为父代的.

https://github.com/daemonl/go_sweetpl

相关问题