I’m going to share the structure I use for templates when building a Django application — either from the ground up or when restructuring an existing application. The process is geared towards reusable apps, but the concepts involved are flexible. This is a framework, of sorts, and a style guide.

This structure evolved organically for me over thousands of hours developing templates and it works well for me. Your mileage may vary.

And, please, you are already organizing templates into app-specific subdirectories, right? Right?

Before we start, I’ll share the structure of one of my basic Django apps, with templates. Gazette is a Django blogging app (yes, another one) that I’ve been working on, and which I will mine for examples throughout this article.

gazette / __init__ . py models . py views . py static / ... templates / gazette / __base . html __l_single_col . html __l_right_sidebar . html __l_left_sidebar . html _article_full . html _article_summary . html _author_list . html _author_name . html _category_list . html _navigation . html _tag_list . html article_detail . html article_list . html author_list . html category_list . html tag_list . html

Know Your Templates

The first principle of my template development process comes straight from The Zen of Python:

Readability counts.

What this means in template development is that I should be able to glance at my template directory and instantly know what purpose each template serves. More importantly, when a client comes to me with a page in their application that requires an update, I shouldn’t have to hunt for which file contains the relevant code. It should require scanning two templates at most.

To this end, I organize all of my templates into three distinct categories: extendable templates, includable templates, and page templates.

Extendable Templates

Extendable templates form the basic structure of your HTML pages. They are templates whose specific purpose is to be extended by other templates with the {% extends %} tag. To keep from conflating my extendables with my page templates I adhere strictly to never calling an extendable directly from a view and never extending a template which is not an extendable. By way of naming convention, I start all my extendable templates with double-underscores, i.e., __base.html .

The most important template is __base.html which is the HTML scaffolding that all of your pages should contain. Generally this template should be pretty minimal. Mine almost always looks like something like this:

{% load staticfiles i18n %} <! DOCTYPE html> <html> <head> {% block meta_tags %}{% endblock %} <title> {% block title %}{% trans "Django Gazette" %}{% endblock %} </title> {% block stylesheets %} <link rel= "stylesheet" href= " {% static "gazette/bootstrap/css/bootstrap.min.css" %} " type= "text/css" /> <link rel= "stylesheet" href= " {% static "gazette/css/base.css" %} " type= "text/css" /> {% endblock %} {% block javascript %} <script src= " {% static "gazette/js/jquery-1.7.2.min.js" %} " type= "text/javascript" ></script> <script src= " {% static "gazette/bootstrap/js/bootstrap.min.js" %} " type= "text/javascript" ></script> {% endblock %} {% block extra_head %}{% endblock %} </head> <body> <header class= "navbar navbar-fixed-top" > {% include "gazette/_navigation.html" %} </header> <div id= "main" role= "main" > <div class= "container" > {% block content %} {% endblock %} </div> </div> </body> </html>

As you can see, I use Bootstrap when I’m starting a new project, but this approach is not Bootstrap-specific.

When I write this base template, I like to code defensively. I think to myself, “If another developer (including myself in six months) comes to this project and needs to build a new template, how can I ensure that they can create any template they want, without having to change the base template.” The answer turns out to be through the use of plenty of obviously-named {% block %} tags to override and extend as necessary. I’ll talk more about {% block %} tags later on.

At this point, if your app is very simple, you may not need much more than the __base.html template to provide your structure. You can move straight on to writing your page templates and includables. But if your app is particularly complex, you may want to build out a more thorough framework with some layout templates.

In Gazette, I use three layout templates, whose names I start with __l_ (again, so I instantly know their purpose): __l_single_col.html , __l_right_sidebar.html , __l_left_sidebar.html . I stash these in the same directory with the other templates, in accordance with the Zen of Python:

Flat is better than nested.

However, if you need many more templates than three, you may want to create a layouts/ subdirectory. When I worked on a project with a particularly complex grid, I created just such a subdirectory and filled it with templates such as layouts/100.html , layouts/25_75.html , layouts/50_50.html , &c.

Here’s an example of one of my layouts, __l_right_sidebar.html :

{% extends "gazette/__base.html" %} {% block content %} <div class= "row" > <div class= "span8" > {% block main_col %}{% endblock %} </div> <div class= "span4" > {% block side_col %}{% endblock %} </div> </div> {% endblock %}

It’s a very simple template — so simple that you might feel it’s unnecessary, but, believe me, this thin layer provides a lot of advantages when you’re building out your page templates later.

Includable Templates

Includable templates are templates that you intend to be included in page templates using the {% include %} tag. As with the extendables, I am strict in mandating that includables adhere to their purpose. You can also think of them as the building blocks that make up your site, glued together by your page templates. There are two primary reasons to make a chunk of your site includable:

because you are going to reuse that particular module on multiple pages and you want to keep your template code DRY . because you want another developer to easily override a particular module in your app without having to gut your template structure entirely.

As always, code defensively: be prepared for other developers (including yourself in six months) to want to modify and override your templates in ways you never dreamed of.

And keep an eye on your balance. Too few includables will make small modifications infuriating to carry out, but too many will create spaghetti code that’s tough to browse.

Page Templates

Page templates are the meat of your app, but if you’ve built up some good extendables and maybe even includables before you get here, you’ll find them pretty easy to put together. They’re really just the glue that holds all your templates together.

Your page templates are the ones that your views will call directly. They link your extendables and your includables together in synchronous harmony. For example, this is article_detail.html :

{% extends "gazette/__l_right_sidebar.html" %} {% block title %}{{ article.title }} | {{ block .super }}{% endblock %} {% block main_col %} {% include "gazette/_article_full.html" %} {% endblock %} {% block side_col %} {% include "gazette/_tag_list.html" with tags = article.tags.all %} {% include "gazette/_category_list.html" with categories = article.categories.all %} {% endblock %}

As you can see, this page uses the __l_right_sidebar.html layout. The main column contains a full article. The side column contains both a tag list and a category list. It’s just about as easy to read as a template can be.

I promised you the layer of layout separation would lead to increased awesomeness later, and it does: if I decide that I’d rather have the tags and categories on the left side of the page, all I have to do is change the first line of article_detail.html to:

{% extends "gazette/__l_left_sidebar.html" %}

and the content will all fall into place, right where I want it to.

Better still, if another developer is overriding my templates and they prefer, say, 75% - 25% layouts to the 66% - 33% layout I wrote into __l_right_sidebar.html , then they can override that template to:

{% extends "gazette/__base.html" %} {% block content %} <div class= "row" > <div class= "span9" > {# this is now 75% of the page #} {% block main_col %}{% endblock %} </div> <div class= "span3" > {# this is now 25% of the page #} {% block side_col %}{% endblock %} </div> </div> {% endblock %}

and all the pages that use that layout will follow suit.

As far as naming convention is concerned, when appropriate, I try to follow the naming conventions that Django’s generic views use, e.g., <object_type>_list.html , <object_type>_detail.html , <object_type>_form.html , &c. If the template you’re writing doesn’t easily fit into that categorization, just try to keep it fairly obvious which views it corresponds to when naming it.

Some Notes on {% block %} and {{ block.super }}

Django’s template inheritance system is wonderfully powerful, and it’s easy to get carried away. I often see structures in base (i.e., extendable) templates where developers place default content in their blocks:

{% block main %} This is content for the front page of my application. {% endblock %}

presumably with the intention of overriding that content when extending that template for use on other pages. I encourage you not to buy into this structure. It conflates your extendables with your pages and makes it harder to know where to look when updating particular template content. (“Is it in frontpage.html or is it in base.html ?”) Instead, think of the block content in your extendables as content that you may want to reuse on various page templates with {{ block.super }} .

The simplest example of this is the <title> element. I often see structures like this in base templates:

<title> {% block page_title %}{% endblock %} Site Title </title>

This not only strikes me as inelegant (Do we put the separator that goes between the page title and the site title — e.g., “Page Title | Site Title” — in the base template or in page templates? What about pages that don’t have page titles?), but limits what a developer can do without modifying the base template. I’d much rather see a simple structure like this in your base templates:

<title> {% block title %} Site Title {% endblock %} </title>

Similarly with CSS or other assets, rather than

<link rel= "stylesheet" type= "text/css" href= "base.css" /> {% block styles %} {% endblock %}

or, heaven forbid,

{% block styles %} <link rel= "stylesheet" type= "text/css" href= "base.css" /> {% endblock %} {% block extra_styles %} {% endblock %}

This is convoluted and unnecessary, when a simple

{% block styles %} <link rel= "stylesheet" type= "text/css" href= "base.css" /> {% endblock %}

will suffice. Later, in your page template, you can add styles with:

{% block styles %} {{ block .super }} <link rel= "stylesheet" type= "text/css" href= "specific_page.css" /> {% endblock %}

Similarly, with the title you can:

<title> {% block title %} Specific Page | {{ block .super }}{% endblock %} </title>

This, to my eyes at least, is more elegant — the blocks are better named, there are fewer of them, they more accurately express the thought behind the structure — and if you want to abandon the default styles or default title for a specific page, without abandoning your base template altogether, you still have the freedom to do so.

{{ block.super }} is a powerful tool. Use it responsibly.

A Few Final Notes

Internationalization

Especially if you’re writing templates for a reusable app, please internationalize your templates. It’s so gloriously easy with the {% trans %} and {% blocktrans %} tags.

{% include %} and {% with %}

For a really long time I was still writing terrible code like:

{% with article.categories.all as categories %} {% include "gazette/_category_list.html" %} {% endwith %}

Until I realized that this superior syntax has been available since Django 1.3:

{% include "gazette/_category_list.html" with categories = article.categories.all %}

For extra bonus encapsulation, try giving your includables exclusive context:

{% include "gazette/_category_list.html" with categories = article.categories.all only %}

Closing Tags

HTML and Django Template Language are, by nature, nested, which sometimes impairs legibility, especially when dealing with long blocks. Django Template Language offers this useful optional syntax for keeping track of your blocks:

{% block camelot %} Pretend this is so much content that you lose track of what block you're in before the end. {% endblock camelot %}

But what about other cases? I often use template comments to mimic this structure for other HTML and template tags:

<div class= "article-content" > A very long article. </div> {# /.article-content #}

which I find greatly improves the legibility of my templates.

Treat HTML and Template Tags Identically

I used to believe that indentation of HTML tags should be treated separately from the indentation of template tags — perhaps out of a misguided belief that the indentation of outputted HTML actually mattered — which led to a lot of code like this:

{% block navigation %} <nav id= "navigation" > {% with bookpage.book.pages.all as bookpages %} <ul class= "book-page-list" > {% for page in bookpages %} {% if page ! = bookpage %} <li><a href= " {{ page.get_absolute_url }} " > {{ page.name }} </a></li> {% else %} <li class= "active" > {{ page.name }} </li> {% endif %} {% endfor %} </ul> {% endwith %} </nav> {% endblock %}

Which, as it turns out is a lot less legible than what you get if you just treat template and HTML tags as equal citizens:

{% block navigation %} <nav id= "navigation" > {% with bookpage.book.pages.all as bookpages %} <ul class= "book-page-list" > {% for page in bookpages %} {% if page ! = bookpage %} <li><a href= " {{ page.get_absolute_url }} " > {{ page.name }} </a></li> {% else %} <li class= "active" > {{ page.name }} </li> {% endif %} {% endfor %} </ul> {% endwith %} </nav> {% endblock %}

And there’s no good reason not to.

What else?

This structure evolved organically for me and continues to evolve. I’ll keep you abreast of further ideas for template architecture. What about you? Do you have particular tips and tricks for keeping templates organized and legible?