Users and abusers of Django’s nifty template inheritance may have found they are unable to do the following in a child template (one that uses the ‘extends’ templatetag):
{% block stuff %}
{% if cond %}
{% block foo %} override foo {% endblock %}
{% else %}
{% block bar %} override bar {% endblock %}
{% endif %}
{% endblock %}
What ends up happening is that both ‘foo’ and ‘bar’ blocks in the base template are overridden.
If you look at the Django source for the ‘block’ and ‘extends’ tags it is easy to see why this doesn’t work.
The render() function of the ExtendsNode class rips out every single block inside it and propagates it “up” to the base template by recursively replacing blocks in parent templates until the base template is reached. This takes place before the contents of block nodes are rendered.
The main consequences of this:
- Block nodes exist outside of flow control, as the snippet above shows
- Template rendering is sped up. All non-extends tags are rendered only once – when the base template is rendered.
Assume we really want to support the snippet I posted. This would result in a massively complex implementation, and sentences like
“Since template inheritance is somewhat similar to class inheritance, we need to implement dynamic dispatch of blocks via virtual function table. To populate the table…”
in the Django mailing list.
I think the current decision is the correct choice. It’s better to have a lightweight rendering engine and put the onus on the developer to get it right.
Here’s another fun thing to try before I go:
base template:{% block outer %}
I'm the outer block
{% block inner %}And I'm inside!{% endblock %}
{% endblock %}
child template:
{% block inner %}
I am so drunk that
{% block outer %}
I reversed the blocks
{% endblock %}
{% endblock %}
Try it!
Would you want the template rendering engine to include code to catch this and any of the myriad other gotchas compiler writers love so much? And have all that error-checking code chugging away in the background with every page you render? I think not.

