This seems like a pretty basic thing to do but although I've been using Django for around a year, I've never run into this scenario yet.
In a lot of templating/web frameworks, template inheritance works a bit differently, in that usually it behaves more like wrappers, so if you have childtemplate.html, parenttemplate.html, and grandparenttemplate.html, then the finally rendering usually looks something like:
grandparent header
parent header
child header
child content
parent content
parent footer
grandparent content
grandparent footer
That's not exactly how it works in Django but I'm wondering how to implement it.
Specifically I have my "child" template, let's just say it's foo.html
. foo.html
optional gets a variable parent_template
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 run into a snag. If parent_template
is a template, that template should wrap the contents of foo.html
and then place the result into 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 render 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 a template in a parent template, and then send the results of that to the base.html
template.
Normally, 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 the parent_template could be blank, then sometimes base.html will be getting just the child_content
block, not the content
block.
Also, I'd like to be able to do this without having to create a bunch of sub-blocks (what if I decide that the foo
application should have its own /foo/base.html
that then calls /base.html
)?
Any ideas?
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 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>
edit:
one way around this problem to get nested blocks is:
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 %}
The other method that i can think of is to wrap the blocks with an {% if ext_templ == 'parent.html' %}
tag but that doesn't seem very dry. I'm curious to see other peoples response to nested blocks as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With