Djangos' built-in template loader (described in the previous section on template loading insiders) will usually fulfill all your template loading needs, but if you have specific loading needs, it's fairly easy to write your own template loader. For example, you can load templates from a database, or directly from the Subversion library using Python bindings, or from a ZIP file.
Each of the template loaders, that is, TEMPLATE_LOADERS, should be able to be called by the following interface:
load_template_source(template_name, template_dirs=None)
The argument template_name is the name of the loaded template (as passed to loader.get_template() or loader.select_template()), and template_dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
If the loader is able to load a template successfully, it should return a tuple: (template_source, template_path). Here template_source is the template string that will be compiled by the template engine, and template_path is the path to the loaded template. Since that path may be displayed to the user for debugging purposes, it should quickly indicate where the template was loaded from.
If the loader fails to load the template, then an exception is thrown.
Each loader function should have a function attribute called is_usable. This attribute is a boolean value that tells the template engine whether this loader is available in the current installation of Python. For example, if the pkg_resources module is not installed, the eggs loader (which is able to load templates from python eggs) should set is_usable to False because pkg_resources must be passed through in order to read data from eggs.
An example will clearly illustrate everything. Here is a template loading function that loads templates from a ZIP file. It uses the custom setting TEMPLATE_ZIP_FILES instead of TEMPLATE_DIRS for the lookup path, and it assumes that every file in this path is a ZIP file containing a template:
from import settings from import TemplateDoesNotExist import zipfile def load_template_source(template_name, template_dirs=None): "Template loader that loads templates from a ZIP file." template_zipfiles = getattr(settings, "TEMPLATE_ZIP_FILES", []) # Try each ZIP file in TEMPLATE_ZIP_FILES. for fname in template_zipfiles: try: z = (fname) source = (template_name) except (IOError, KeyError): continue () # We found a template, so return the source. template_path = "%s:%s" % (fname, template_name) return (source, template_path) # If we reach here, the template couldn't be loaded raise TemplateDoesNotExist(template_name) # This loader is always usable (since zipfile is included with Python) load_template_source.is_usable = True
The last step left for us to use it is to add it to TEMPLATE_LOADERS. If we're putting this code into a package called mysite.zip_loader, then we're going to add mysite.zip_loader.load_template_source to TEMPLATE_LOADERS.