-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: text/template: execute "parent" template when inheriting #48266
Comments
cc @robpike |
Change https://golang.org/cl/348669 mentions this issue: |
cc @adg |
fwiw I don't really think If the parent template does need to be accessed by a child template, currently it can be done by giving them different names: https://play.golang.org/p/kqYH2h1wW24 var parenttext = `
{{ define "content" }}{{ template "content.parent" }}{{ end }}
{{ define "content.parent" -}}
this is the parent
{{ end }}
`
var childtext = `
{{ define "content" -}}
{{ template "content.parent" -}}
this is the child
{{ end }}
`
func main() {
parent := template.Must(template.New("parent").Parse(parenttext))
child := template.Must(template.New("parent").Parse(parenttext))
child = template.Must(child.New("child").Parse(childtext))
fmt.Println("== parent output ==")
parent.ExecuteTemplate(os.Stdout, "content", nil)
fmt.Println("== child output ==")
child.ExecuteTemplate(os.Stdout, "content", nil)
} output
|
It's true that the template package does not have the kind of inheritance found in some other packages. But I'm confused about what this can mean. The "parent" of a "child" would have to be the template that called the child, but that template has already emitted output, so why does it make sense to reinvoke the parent a second time? I'm not sure that this idea of inheritance fits into the model that we already have for templates. |
This proposal has been added to the active column of the proposals project |
Another related issue, with an alternative design: #23774 |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
This describes a proposal to change the
text/template
language to support executing a previously defined template with the same name within a template's current definition, which can be useful when a template inherits from another.Other template languages, for example, Jinja and Django, support the concept of inheritance, where a base or parent template can be overridden in part by defining sub-template within itself, of which a child template can then redefine (or choose to leave default). This is a natural fit for contexts such as web page templates, where the shell of the page, which defines things like headers and footers, navigation, and stylesheets and common JavaScript includes, remains the same across multiple pages, but individual pages want to set their own title, main body content, and so forth. Go's
text/template
already supports template inheritance via the{{block}}
and{{define}}
constructs. Crucially, however, other languages support child templates accessing the default contents of parent blocks (in the case of Jinja and Django, via thesuper()
function or{{ block.super }}
tag, respectively) from within the template being overridden. This is a useful property to have, for example, in the case of a web page, where a base template may define a site-wide title that child templates can include while also adding their own specific page title.By construction, templates may only reside with one association. However, it can be useful to have templates inherit from previously defined ones, as mentioned. When a template has the same name as one that has been previously defined and associated, the current behavior is that the new template entirely replaces the previously defined one. What is proposed then is both a) a way for a template to reference within its definition the template that it is redefining and b) a way for template associations to track successive generations of templates with the same name (because they may inherit to an arbitrary depth), in the order in which they are redefined.
One way to address a) would be to introduce the
parent
keyword to the template language. In template execution nodes, instead of a name string of the template to be executed, the keywordparent
could be used instead to indicate that the template of the same name (i.e., the one currently being defined) but of the previous generation should be executed at that point in the template definition. If we use the parent-child metaphor to describe the relationship between two templates with the same name where one is defined after the other in the same association, then a child could produce the contents of its parent with{{template parent .}}
.Example
To motivate this change and explain its behavior, let's consider an example. We'll review a potentially common use-case for it, that of a base web page template and subsequent overriding templates.
This example has a base template, a template for an index page and an about page, and a template for a contact page nested under the about section.
The base template:
Suppose the base template is parsed in Go and named
base.html
.This template has 4 associated templates:
base.html
,title
,content
, andfooter
.The index page template
index.html
:This template is executed as normal:
Which produces, as expected:
This is standard template inheritance as it exists today.
The about page template
about.html
:Notice the use of
{{template parent .}}
in the definition of thetitle
template.Which produces:
Finally, to demonstrate that the use of
parent
can be nested arbitrarily deep, the contact pagecontact.html
:The intent is to include bits of the about page in the contact page.
Note that the about template is cloned in this step.
This produces:
Previous related discussion
In the issue where template inheritance was first discussed, which ultimately led to
block
being added to the language, this comment mentions accessing the parent template contents from within a child template. However, it does not appear this comment or the notion was ever followed-up on.The text was updated successfully, but these errors were encountered: