Django: Template Inheritance

Coffee Beans

In an effort to get some work done on personal projects, I decided that I need to program them in a language I enjoy more than PHP. The idea is that it will seem less like work and more like fun. It seems to be working so far, though there’s always a bit of a learning curve to get used to a new framework.

Speaking of frameworks, I chose Django, since it seems pretty mature and well thought-out.

One of the things that really strikes me as a really good idea (aside from ORM done right and and awesome automatic admin interface) is the concept of “template inheritance”.

Template inheritance allows you to define a base template with blocks, and then in “child” templates, to simply override those blocks which you wish to replace. This really helps to reduce the amount of template code, and even the number of template files, that you have to write.

The (Smarty) annoying way

I’ve used Smarty a lot in the past (and continue to do so on a regular basis), and the one thing that’s always annoyed me is that there’s not a good way to insert the content of a template into the middle of another template.

Sure, you can include templates, but that does you no good if you don’t know what you’re going to be including. Also, you have to include multiple templates in various different places, and store all of them in separate files. You could assign variables to indicate which templates need to be included for a given page, and then include the templates referenced in the variable, but this violates the separation of display and logic (though admittedly in the opposite direction than usual).

The other way to accomplish the same thing without the violation of separation of interests is to have a header and footer template, both of which are included in every single other template. This is a huge pain in the ass to do, and leads to fun errors. It’s really easy to get mismatched or missing tags when the opening and closing tags are in two different files.

I die a little bit inside whenever I have to include a header and a footer template from within my own template.

Example:

    {* header.tpl *}
    <html>
        <head>
            <title>{$title}</title>
        </head>
        <body>
            <h1>{$title}</h1>
    {* page.tpl *}
            {include file="header.tpl"}
            <p>
                {$content_body}
            </p>
            {include file="footer.tpl"}
    {* footer.tpl *}
            <p class="footer">{$copy}</p>
        </body>
    </html>

The (Django) template inheritance way

With template inheritance, you simply define a base template, and then extend that template, filling in (or not) the various blocks defined in the base template. Any blocks which you don’t define will be filled in from the base template.

Inheritance works to any depth so it’s easy to have subsections of a site share design elements and just redefine the central content.

Example:

    {% templatetag opencomment %} base.html {% templatetag closecomment %}
    <html>
        <head>
            <title>{% templatetag openvariable %} title {% templatetag closevariable %}</title>
        </head>
        <body>
            <h1>{% templatetag openvariable %} title {% templatetag closevariable %}</h1>
    
            {% templatetag openblock %} block content {% templatetag closeblock %}{% templatetag openblock %} endblock {% templatetag closeblock %}
    
            <p class="footer">{% templatetag openvariable %} copy {% templatetag closevariable %}</p>
        </body>
    </html>
    {% templatetag opencomment %} page.html {% templatetag closecomment %}
    {% templatetag openblock %} extend "base.html" {% templatetag closeblock %}
            {% templatetag openblock %} block content {% templatetag closeblock %}
            <p>
                {$content_body}
            </p>
            {% templatetag openblock %} endblock content {% templatetag closeblock %}

Using template inheritance, there’s only one file to look in too see where most of the page is coming from, and when editing the base template you don’t have to worry about opening two different files to be sure that all of their tags are matched up.

More about Django template inheritance, and the Django template language in general can be found at the Django manual

This is the first of what will probably be several posts on Django. There are plenty more awesome features which I also like. Do you have any suggestions for interesting Django topics for me to write about? If so, let me know!
blog comments powered by Disqus