Nested django templates

This seems like a pretty simple task, but although I have been using Django for about a year, I have not yet come across this scenario.

In many template templates / template inheritance, template inheritance works differently since it usually behaves more like wrappers, so if you have childtemplate.html, parenttemplate.html and grandparenttemplate.html, then the final rendering usually looks something like this:

grandparent header parent header child header child content parent content parent footer grandparent content grandparent footer 

This is not exactly how it works in Django, but I am wondering how to implement it.

In particular, I have my "child" template, let it just say foo.html . foo.html optional gets the parent_template variable or defaults to "base.html"

 {% extends parent_template|default:"base.html" %} {% block content %} I am a foo and my title is {{ foo.title }} {% endblock content %} 

So, this is where I ran into the problem. If parent_template is a template, this template should wrap the contents of foo.html , and then put the result in base.html :

 {% extends "base.html" %} {% something_magical_here %} <div>parent header</div> # content of foo.html <div>parent footer</div> {% end_something_magical_here %} 

And then in base.html :

 <html> ... snip ... <div id="content"> {% something_else_magical %} # content of parent_template rendering, or just foo.html if no parent_template given {% end_something_else_magical %} 

which should be displayed as

 <html> ... snip ... <div id="content"> <div>parent header</div> I am a foo and my title is Bar <div>parent footer</div> 

if parent_template is set and

 <html> ... snip ... <div id="content"> I am a foo and my title is Bar 

if it is not.

I hope my problem is clear: I need to (optionally) wrap the template in the parent template and then send the results of this to the base.html template.

Usually something like this might work:

 #foo.html {% extends "parent.html" %} {% block child_content %} I am a foo and my title is {{ foo.title }} {% endblock child_content %} #parent.html {% extends "base.html" %} {% block content %} parent header {% block child_content %}{% endblock child_content %} parent content parent footer #base.html base header {% block content %}{% endblock content %} base content base footer 

However, since parent_template may be empty, sometimes base.html will only receive the child_content block, not the content block.

Also, I would like to be able to do this without creating a bunch of subblocks (what if I decide that the foo application should have its own /foo/base.html , which then calls /base.html ))

Any ideas?

+4
source share
1 answer

The extends template tag can take a variable argument.

So:

 base.html {% block content %} <p>BASE</p> {% endblock %} parent.html {% extends "base.html" %} {% block content %} {{ block.super }} <p>PARENT</p> {% endblock %} foo.html {% extends ext_templ %} {% block content %} {{ block.super }} <p>FOO</p> {% endblock %} 

using the base:

 return render_to_response('foo.html', {'ext_templ':'base.html'}) 

gives you:

 <p>BASE</p> <p>FOO</p> 

using parent:

 return render_to_response('foo.html', {'ext_templ':'parent.html'}) 

gives you:

 <p>BASE</p> <p>PARENT</p> <p>FOO</p> 

change

One way around this problem for nested blocks:

 base.html {% block content %} {% block top %} <p>BASE START</p> {% endblock %} {% block bot %} <p>BASE END</p> {% endblock %} {% endblock %} parent.html {% extends "base.html" %} {% block top %} {{ block.super }} <p>PARENT</p> {% endblock %} {% block bot %} <p>PARENT</p> {{ block.super }} {% endblock %} foo.html {% extends ext_templ %} {% block top %} {{ block.super }} <p>FOO</p> {% endblock %} {% block bot %} <p>FOO END</p> {{ block.super }} {% endblock %} 

Another method I can think of is to wrap the blocks with the {% if ext_templ == 'parent.html' %} tag, but that doesn't seem very dry. I am curious to see the reaction of other peoples to nested blocks.

+9
source

All Articles