El libro de Django 1.0

10.5. Escribir cargadores de plantillas personalizados

Los cargadores de plantillas incluidos con Django (descritos en la sección anterior "Etiquetas de inclusión") normalmente son suficientes para tus necesidades de carga de plantillas, pero es muy sencillo escribir el tuyo propio si necesitas alguna lógica especial en dicha carga. Por ejemplo podrías cargar plantillas desde una base de datos, o directamente desde un repositorio Subversion usando las librerías (bindings) Python de Subversion, o (como veremos) desde un archivo ZIP.

Un cargador de plantillas — esto es, cada entrada en la variables de configuración TEMPLATE_LOADERS — debe ser un objeto invocable (callable) con la siguiente interfaz:

load_template_source(template_name, template_dirs=None)

El argumento template_name es el nombre de la plantilla a cargar (tal como fue pasado a loader.get_template() o loader.select_template()) y template_dirs es una lista opcional de directorios en los que se buscará en lugar de TEMPLATE_DIRS.

Si un cargador es capaz de cargar en forma exitosa una plantilla, debe retornar una tupla: (template_source, template_path). Donde template_source es la cadena de plantilla que será compilada por la maquinaria de plantillas, y template_path es la ruta desde la cual fue cargada la plantilla. Dicha ruta podría ser presentada al usuario para fines de depuración así que debe identificar en forma rápida desde dónde fue cargada la plantilla.

Si al cargador no le es posible cargar una plantilla, debe lanzar django.template.TemplateDoesNotExist.

Cada función del cargador debe también poseer un atributo de función is_usable. Este es un Booleano que le informa a la maquinaria de plantillas si este cargador está disponible en la instalación de Python actual. Por ejemplo el cargador desde eggs (que es capaz de cargar plantillas desde eggs Python) fija is_usable a False si el módulo pkg_resources no se encuentra instalado, porque pkg_resources es necesario para leer datos desde eggs.

Un ejemplo ayudará a clarificar todo esto. Aquí tenemos una función cargadora de plantillas que puede cargar plantillas desde un archivo ZIP. Usa una variable de configuración personalizada TEMPLATE_ZIP_FILES como una ruta de búsqueda en lugar de TEMPLATE_DIRS y espera que cada ítem en dicha ruta sea un archivo ZIP contiendo plantillas:

import zipfile
from django.conf import settings
from django.template import TemplateDoesNotExist

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 = zipfile.ZipFile(fname)
            source = z.read(template_name)
        except (IOError, KeyError):
            continue
        z.close()
        # 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

El único paso restante si deseamos usar este cargador es agregarlo a la variable de configuración TEMPLATE_LOADERS. Si pusiéramos este código en un paquete llamado mysite.zip_loader entonces agregaremos mysite.zip_loader.load_template_source a TEMPLATE_LOADERS.