Nested Templates Best Practices and Examples

5,035 views
Skip to first unread message

Alec

unread,
Aug 12, 2012, 4:07:12 PM8/12/12
to golan...@googlegroups.com
I have seen Jan's template chapter ( http://jan.newmarch.name/go/template/chapter-template.html), but didn't find the best way to nest templates inside each other. 

My particular problem is that my templates are set up like this:

//_base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{template "title" . }}</title>
</head>
<body>
<section id="contents">
{{ template "content" . }}
</section>
<footer id="footer">
...stuff....
</footer>
</body>
</html>


//index.html:
{{define "title" }}Home Title{{ end }}

{{define "content"}}
... Stuff ...

{{ .Content}}
{{end}}


//illustration.html:

  {{define "title" } Title {{ end }}

  {{define "content"}}
... stuff....

{{end}}


The program compiles fine, but when I try to run the binary, it spits out the error: panic: template: redefinition of template "title" 

Does anyone have any recommendations for strategies for this or can point me to some examples and/or best practices for nesting templates?

Thanks in advance for you help!

Andrew Gerrand

unread,
Aug 12, 2012, 11:32:24 PM8/12/12
to Alec, golan...@googlegroups.com

You need to call ParseFiles twice and create two different *template.Template values. One with _base and index, and one with _base and illustration.

Andrew

Rodrigo Moraes

unread,
Aug 13, 2012, 4:55:10 AM8/13/12
to golang-nuts
On Aug 13, 12:32 am, Andrew Gerrand wrote:
> You need to call ParseFiles twice and create two different
> *template.Template values. One with _base and index, and one with _base and
> illustration.

The main purpose of adding a {{block}}/{{fill}} actions to text/
template is to allow common assembling like this to be done in
templates, and not in code. As in:

//_base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{block "title"}}Default title{{end}}</title>
</head>
<body>
<section id="contents">
{{block "content"}}Default content{{end}}
</section>
<footer id="footer">
...stuff....
</footer>
</body>
</html>
//index.html:
{{fill "_base.html" .}}
{{block "title"}}Home Title{{end}}
{{block "content"}}
... Stuff ...
{{ .Content}}
{{end}}
{{end}}
//illustration.html:
{{fill "_base.html" .}}
{{block "title"}}Title{{end}}
{{block "content"}}
... stuff....
{{end}}
{{end}}

-- rodrigo

Rodrigo Moraes

unread,
Aug 13, 2012, 5:09:36 AM8/13/12
to golang-nuts
On Aug 12, 5:07 pm, Alec wrote:
> Does anyone have any recommendations for strategies for this or can point
> me to some examples and/or best practices for nesting templates?

One neat idea (from +Christoph Hack) is to create a convention to
parse the templates. Organize template sets in directories, and create
a function to parse each template together with "_base.html" in the
current and parent directories, when available. For the directory
structure:

- templates
|- _base.html
|- index.html
|- illustration.html
|- /foo
| |- _base.html
| |- index.html

...you'll end with the template sets:

- "index.html": including _base.html and index.html
- "illustration.html": including _base.html and illustration.html
- "foo/index.html": including _base.html, foo/_base.html, and foo/
index.html

-- rodrigo

Alec

unread,
Aug 13, 2012, 8:14:21 AM8/13/12
to golan...@googlegroups.com
Rodrigo,

I really like the idea of what you proposed there, but I can't seem to get it to work. 

I get the error: panic: template: _Base.html:4: function "block" not defined

I can't find any documentation on the {{block}} functionality, other than your own gist. The gist has slightly different syntax than what you posted above, but neither seem to work. 

Could it be that I am using html/template, instead of the text/template that your gist refers to?

Rodrigo Moraes

unread,
Aug 13, 2012, 8:26:47 AM8/13/12
to golang-nuts
On Aug 13, 9:14 am, Alec wrote:
> I really like the idea of what you proposed there, but I can't seem to get
> it to work.

That really doesn't work with text/template. I'm trying to push the
proposal to Andrew. ;)

> The gist has slightly different
> syntax than what you posted above, but neither seem to work.

The mechanics and implementation evolved a bit. I can post it
somewhere if you are really interested, but that would mean you'd need
to use a fork of text/template and html/template. Not a good idea
really. :/

-- rodrigo

André Moraes

unread,
Aug 13, 2012, 8:36:08 AM8/13/12
to Rodrigo Moraes, Alec Loudenback, golang-nuts
On Mon, Aug 13, 2012 at 6:09 AM, Rodrigo Moraes
<rodrigo...@gmail.com> wrote:
> On Aug 12, 5:07 pm, Alec wrote:
>> Does anyone have any recommendations for strategies for this or can point
>> me to some examples and/or best practices for nesting templates?
>
> One neat idea (from +Christoph Hack) is to create a convention to
> parse the templates. Organize template sets in directories, and create
> a function to parse each template together with "_base.html" in the
> current and parent directories, when available. For the directory
> structure:

I am using this concept in one of my projects and it works very well.
The code for the parsing of templates is more complicated than just
calling ParseFiles, since you need to manually detect when a file has
the special name and use that instead of the default. But all this
logic goes into a single function used to construct the template
object.

One extra benefit is that each "block" corresponds to a file and this
helps a lot with project organization.

--
André Moraes
http://amoraes.info

si guy

unread,
Aug 13, 2012, 5:08:33 PM8/13/12
to golan...@googlegroups.com
Block would also hide complexity of your view logic... When why not just have a man-in-the-middle set of functions to handle this, rather than complicating the template system?
I like to use a map of templates initialized at boot using parseglob etc. to setup all of the template nesting, why does it need to be more complex?
Would there be runtime tradeoffs?
Sorry to be pessimistic but this sounds like it will move a lot of view logic out of go code and into template code, which is harder to understand and debug, especially when it is mingled amongst HTML.

I wrote php for a while doing mvc pattern apps, and keeping view logic out of the templates proved massively beneficial. I think that is what is being replicated here, and I'm not sure the costs to complexity are outweighed by the benefits for a large web app, perhaps a small app yes, but wouldn't you rather debug go code than template code?

Thanks,
-Simon Watt

Rodrigo Moraes

unread,
Aug 13, 2012, 5:59:37 PM8/13/12
to golang-nuts
On Aug 13, 6:08 pm, si guy wrote:
> Block would also hide complexity of your view logic... When why not just have a man-in-the-middle set of functions to handle this, rather than complicating the template system?
> I like to use a map of templates initialized at boot using parseglob etc. to setup all of the template nesting, why does it need to be more complex?

Blocks makes templates more self-contained and simpler to write and
understand. We remove some cognitive load -- the "which/how templates
are assembled in this project?" part of understanding a template set.
And besides, this is the template engine job.

You're seeing a lot of complexity but it is a rather simple concept,
really. And in terms of implementation, my current version adds about
200 lines to text/template.

> Would there be runtime tradeoffs?

No, it is really really absurdly cheap to parse and execute. It is
like an {{if}}.

> Sorry to be pessimistic but this sounds like it will move a lot of view logic out of go code and into template code, which is harder to understand and debug, especially when it is mingled amongst HTML.

I believe it is the opposite. You can parse a larger set of templates
and because they are self-contained, just need to read templates to
know what is going on, independently of the strategy used to load and
assemble them. That said, text/template needs some better debugging
messages.

> I wrote php for a while doing mvc pattern apps, and keeping view logic out of the templates proved massively beneficial.

But blocks are not view logic. They are template logic (as in template
from MVT). It's just some basic assembling done by the template
author.

-- rodrigo

Andrew Gerrand

unread,
Aug 13, 2012, 9:02:58 PM8/13/12
to Rodrigo Moraes, golang-nuts
I see the need here.

But now I'm wondering whether a file naming and layout convention and
some support code to automatically parse such files would be better
than adding to the template language.

Ultimately it's about providing a convenient way to solve the common
problem, and with a file layout convention we might kill two birds
with one stone, without removing any flexibility.

I'm really just thinking out loud here.

Andrew

Rodrigo Moraes

unread,
Aug 13, 2012, 9:42:27 PM8/13/12
to golang-nuts
On Aug 13, 10:02 pm, Andrew Gerrand wrote:
> But now I'm wondering whether a file naming and layout convention and
> some support code to automatically parse such files would be better
> than adding to the template language.
>
> Ultimately it's about providing a convenient way to solve the common
> problem, and with a file layout convention we might kill two birds
> with one stone, without removing any flexibility.

That's reasonable, and the best solution for what exists. A little old-
school, not ideal I'd say, but reasonable.

For the record, the code for the block mechanics I posted earlier is
here:

http://codereview.appspot.com/6447044/

{{fill}} is essentially a {{template}} action that has child actions:
{{block}}'s that replace the ones in the called template.

-- rodrigo

Joubin Houshyar

unread,
Aug 13, 2012, 11:30:17 PM8/13/12
to golan...@googlegroups.com, Rodrigo Moraes


On Monday, August 13, 2012 9:02:58 PM UTC-4, Andrew Gerrand wrote:
I see the need here.

But now I'm wondering whether a file naming and layout convention and
some support code to automatically parse such files would be better
than adding to the template language.

This is what I'm doing and it works quite well.  Hierarchical template source trees, with child override of parent.  Using sibling property files can decouple the naming convention from the generalized engine (which basically is a very thin layer over text/template).

tomwilde

unread,
Aug 15, 2012, 1:18:27 PM8/15/12
to golan...@googlegroups.com, Rodrigo Moraes
I agree, the templating engine should be simple and intuitive. Even for people that don't know anything about Go.
Normally it will be designers, with limited to no knowledge of Go and how it works, who will be writing the templates.
I would even dare saying that the current implementation, although being awesome is already too complex. Take a look at {{ mustache }} - it's dead simple.

Rodrigo Moraes

unread,
Aug 16, 2012, 5:05:30 AM8/16/12
to golang-nuts
On Aug 15, 2:18 pm, tomwilde wrote:
> I would even dare saying that the current implementation, although being
> awesome is already too complex. Take a look at {{ mustache }} - it's dead
> simple.

You may be right.

-- rodrigo

lulu Lee

unread,
Aug 16, 2012, 8:23:20 AM8/16/12
to Rodrigo Moraes, golang-nuts
here is the same in goku: https://github.com/QLeelulu/goku#layout
you can only paser the template and it's layout at a time.



--
@QLeelulu | FaWave, Net4 Team | qlee...@gmail.com | 学海无涯,回头是岸 
Reply all
Reply to author
Forward
0 new messages