Django’s templating system is one of its strongest points, in my opinion, and one of it’s coolest features it the “fallback” system used for locating templates. When used wisely, it can allow for a situation in which you can literally design an entire site by creating only one HTML file.
settings.py file, you configure your
TEMPLATE_DIRS variable. This is simply a Python tuple representing filesystem paths to the locations your templates reside. For example:
TEMPLATE_DIRS = ( '/home/jcroft/webapps/django/jeffcroft.com/templates2', '/home/jcroft/webapps/django/jeffcroft.com/templates1', )
Here, we’ve got two directories containing templates:
templates2. Whenever a Django app attempts to load a template, it will look in these two paths to find it. For example, if your blog application needs a template called
blog/entry_detail.html, it will first look for it in
.../templates2/blog/entry_detail.html. If it’s not found, it will “fallback” to
.../templates1/blog/entry_detail.html (if it’s still not found, Django will return an error.)
Most Django sites are made up of several plug-and-play “apps”. For example, jeffcroft.com includes a blog app, a bookmark app, a tumblelog app, an events app, and more. Each of these apps are collected into a “project”, which often represents a single site (jeffcroft.com is a Django project, for example). As I build new Django apps, I store them in a single directory (which is a Python module). In my case, this directory is called “savoy” (a clever name we’ve come up with for our suite of Django apps). So, we’ve got
savoy/events, and so forth. But we also have
savoy/templates. This is what I like to call “default” templates. This directory contains simple templates for all the apps.
All of the templates in this directory “extend”
base.html. If you aren’t familiar with Django’s template inheritance model, this basically means that
base.html will act as a parent template to, for example,
blog/entry_detail.html, and the contents of
entry_detail.html will get interjected into
base.html. If this isn’t making sense, you might check out a post I wrote on Django template inheritance back in 2006.
When I set up a new Django project (again, such as jeffcroft.com), I include the Savoy default template path in
TEMPLATE_DIRS, but precede it with a “site-specific” template path. Like this:
TEMPLATE_DIRS = ( '/home/jcroft/webapps/django/jeffcroft.com/templates', '/home/jcroft/webapps/django/savoy/templates', )
We know the
savoy/templates directory is full of default templates. Since we’ve just set it up, let’s assume the
jeffcroft.com/templates directory is empty. So what happens now when our blog app needs
blog/entry_detail.html? It looks in
jeffcroft.com/templates/blog/entry_detail.html, but doesn’t find it, so it falls back to
...savoy/templates/blog/entry_detail.html. Remember that
entry_detail.html, along with all the Savoy default templates, extend
base.html. So the same thing happens again: the system looks in
jeffcroft.com/templates/base.html, doesn’t find it, so it uses
Remember I said this could lead to a situation where all you have to do is create one HTML file to design a site?
base.html is that one file. If you create a new
jeffcroft.com/templates, it will be used instead of the one in ‘
base.html file will contain links to your CSS files, your header, footer, sidebar, and so forth — the bulk of your design. Suddenly, by creating one file, you’ve got a full working site in your look and feel.
We used this model extensively at World Online when I was there. We sold a Django-based CMS product called Ellington, which came with a set of default templates. These defaults weren’t much to look at, but they did output nice, clean, semantic HTML for every app and every page in the system (and there were a lot). When newspaper or magazine would purchase Ellington from us, all they had to do was create a
base.html file encapsulating their site’s look and feel. Suddenly, they have a working site that functions for their brand.
After that, they may dig in and find that individual templates, such as our
entry_detail.html example, weren’t quite to their liking. All they needed to do was make a copy of
ellington/blogs/entry_detail.html into their site-specific directory (say,
washingtonpost/blogs/entry_detail.html) and tweak to their heart’s content.
It’s really an elegant system. If you’re creating Django apps, I suggest that you create a set of default templates that output clean, simple HTML and extend the Django convention of
base.html. Doing so lets you (or others, if your apps are publicly available) get started using them very quickly by simply creating a replacement
base.html file. Nathan Borror’s Django Basic Apps are a great example of a suite of apps that work exactly like this.