如何使用空模板覆盖模板块?

huangapple go评论85阅读模式
英文:

How can I override a template block with an empty template?

问题

在我的基本模板中,我使用text/html定义了一个名为block的块,其中包含默认内容。在某些情况下,我希望这个块是空的,所以我认为我可以重新定义它的名称,并使其不包含任何内容,如下所示:

{{ block "something" . }}
    <h1>Default content</h1>
{{ end }}

// 在不需要 "something" 的地方...
{{ define "something" }}{{ end }}

不知何故,Go 似乎认为这个定义是“零”,并且仍然会渲染默认内容,除非我在定义中放入任何非空白内容。

我在 Golang 仓库上找到了这个问题,它在Playground 示例中很好地描述了同样的情况:

package main

import (
	"fmt"
	"os"
	"runtime"
	"text/template"
)

func main() {

	fmt.Printf("Version: %q\n", runtime.Version())

	t, err := template.New("master").Parse(`{{block "area51" .}}Original Content{{end}}`)
	if err != nil {
		panic(err)
	}
	t, err = t.New("other_template").Parse(`{{define "area51"}}{{end}}`)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Output:\n")
	if err := t.ExecuteTemplate(os.Stdout, "master", nil); err != nil {
		panic(err)
	}

	fmt.Printf("\n")

}

奇怪的是,该问题提到它已经修复(如果我理解正确的话),但对我来说不起作用,无论是在 1.8.1+ 还是 1.9 版本。

这是 Golang 的一个 bug 还是方法有问题?我需要以不同的方式重新定义块,使其为空吗?

英文:

Using text/html I define a block in my base template, containing default content. In some situations I would like this block to be empty, so I thought I could just re-define its name and make it contain nothing like:

{{ block &quot;something&quot; . }}
    &lt;h1&gt;Default content&lt;/h1&gt;
{{ end }}

// later in a place that does not want &quot;something&quot; ...
{{ define &quot;something&quot; }}{{ end }}

Somehow Go seems to think that this definition is "Zero" and will still render the default content unless I put any non-whitespace content into the definition.

I found this issue on the Golang repo which describes the very same thing nicely in a Playground example:

package main

import (
	&quot;fmt&quot;
	&quot;os&quot;
	&quot;runtime&quot;
	&quot;text/template&quot;
)

func main() {

	fmt.Printf(&quot;Version: %q\n&quot;, runtime.Version())

	t, err := template.New(&quot;master&quot;).Parse(`{{block &quot;area51&quot; .}}Original Content{{end}}`)
	if err != nil {
		panic(err)
	}
	t, err = t.New(&quot;other_template&quot;).Parse(`{{define &quot;area51&quot;}}{{end}}`)
	if err != nil {
		panic(err)
	}

	fmt.Printf(&quot;Output:\n&quot;)
	if err := t.ExecuteTemplate(os.Stdout, &quot;master&quot;, nil); err != nil {
		panic(err)
	}

	fmt.Printf(&quot;\n&quot;)

}

Weirdly, the issue mention it is fixed (and landed in 1.8.1 if I understand it correctly), but it does not work for me, neither with 1.8.1+ nor 1.9.

Is this a bug in Golang or is the approach flawed? Do I need to do anything differently in order to re-define the block so that it renders empty?

答案1

得分: 3

这是预期的行为。在Template.Parse()中有记录:

> 模板可以在对t或任何关联模板的第一次执行之前,通过连续调用Parse来重新定义。**如果模板定义的主体只包含空格和注释,则被视为空,并且不会替换现有模板的主体。**这允许使用Parse添加新的命名模板定义,而不会覆盖主模板的主体。

因此,你不能“擦除”已定义的模板(不能将其内容替换为空)。

如果你“有条件地”需要它,可以使用{{if}}操作来决定是否调用模板。或者你可以在模板内部放置一个{{if}},模板本身可以选择不渲染任何内容。在这种情况下,你必须确保传递适当的参数来控制模板将渲染什么。

附注:如果你正在使用HTML模板,应该始终使用html/template而不是text/template,因为前者提供与text/template包相同的接口,同时还提供上下文转义以生成安全的HTML输出,防止代码注入。

英文:

This is the expected behavior. This is documented at Template.Parse():

> Templates can be redefined in successive calls to Parse, before the first use of Execute on t or any associated template. A template definition with a body containing only white space and comments is considered empty and will not replace an existing template's body. This allows using Parse to add new named template definitions without overwriting the main template body.

So you can't "erase" an already defined template (you can't replace its content to be empty).

If you "conditionally" need it, then use an {{if}} action to decide if the template is to be called. Alternatively you may put an {{if}} inside the template, and the template itself may choose not to render anything. In this case you have to make sure to pass the proper argument that controls what the template will render.

P.S. If you're working with HTML templates, you should always use html/template instead of text/template, as the former provides the same interface as package text/template but also provides contextual escaping to generate HTML output safe against code injection.

huangapple
  • 本文由 发表于 2017年9月12日 18:48:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/46174445.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定