Jinja

Template Loaders

Navigation

Contents

This part of the documentation explains how to use and write a template loader.

Builtin Loaders

ChoiceLoader

A loader that tries multiple loaders in the order they are given to the ChoiceLoader:

from jinja import ChoiceLoader, FileSystemLoader
loader1 = FileSystemLoader("templates1")
loader2 = FileSystemLoader("templates2")
loader = ChoiceLoader([loader1, loader2])
DictLoader

Load templates from a given dict:

from jinja import Environment, DictLoader
e = Environment(loader=DictLoader(dict(
    layout='...',
    index='{% extends 'layout' %}...'
)))
FileSystemLoader

Loads templates from the filesystem:

from jinja import Environment, FileSystemLoader
e = Environment(loader=FileSystemLoader('templates/'))

You can pass the following keyword arguments to the loader on initialisation:

searchpath String with the path to the templates on the filesystem.
use_memcache Set this to True to enable memory caching. This is usually a good idea in production mode, but disable it during development since it won't reload template changes automatically. This only works in persistent environments like FastCGI.
memcache_size Number of template instance you want to cache. Defaults to 40.
cache_folder Set this to an existing directory to enable caching of templates on the file system. Note that this only affects templates transformed into python code. Default is None which means that caching is disabled.
auto_reload Set this to False for a slightly better performance. In that case Jinja won't check for template changes on the filesystem.
FunctionLoader

Loads templates by calling a function which has to return a string or None if an error occoured.

from jinja import Environment, FunctionLoader

def my_load_func(template_name):
    if template_name == 'foo':
        return '...'

e = Environment(loader=FunctionLoader(my_load_func))

Because the interface is limited there is no way to cache such templates. Usually you should try to use a loader with a more solid backend.

You can pass the following keyword arguments to the loader on initialisation:

loader_func Function that takes the name of the template to load. If it returns a string or unicode object it's used to load a template. If the return value is None it's considered missing.
getmtime_func Function used to check if templates requires reloading. Has to return the UNIX timestamp of the last template change or -1 if this template does not exist or requires updates at any cost.
use_memcache Set this to True to enable memory caching. This is usually a good idea in production mode, but disable it during development since it won't reload template changes automatically. This only works in persistent environments like FastCGI.
memcache_size Number of template instance you want to cache. Defaults to 40.
cache_folder Set this to an existing directory to enable caching of templates on the file system. Note that this only affects templates transformed into python code. Default is None which means that caching is disabled.
auto_reload Set this to False for a slightly better performance. In that case of getmtime_func not being provided this won't have an effect.
PackageLoader

Loads templates from python packages using setuptools.

from jinja import Environment, PackageLoader
e = Environment(loader=PackageLoader('yourapp', 'template/path'))

You can pass the following keyword arguments to the loader on initialisation:

package_name Name of the package containing the templates.
package_path Path of the templates inside the package.
use_memcache Set this to True to enable memory caching. This is usually a good idea in production mode, but disable it during development since it won't reload template changes automatically. This only works in persistent environments like FastCGI.
memcache_size Number of template instance you want to cache. Defaults to 40.
cache_folder Set this to an existing directory to enable caching of templates on the file system. Note that this only affects templates transformed into python code. Default is None which means that caching is disabled.
auto_reload Set this to False for a slightly better performance. In that case Jinja won't check for template changes on the filesystem. If the templates are inside of an egg file this won't have an effect.

Developing Loaders

Template loaders are just normal Python classes that have to provide some functions used to load and translate templates. Because some of the tasks a loader has to do are redundant there are some classes that make loader development easier.

Here the implementation of a simple loader based on the BaseLoader from jinja.loaders:

import codecs
from os.path import join
from jinja.loaders import BaseLoader
from jinja.exceptions import TemplateNotFound

class SimpleLoader(BaseLoader):

    def __init__(self, path):
        self.path = path

    def get_source(self, environment, name, parent):
        filename = join(self.path, name)
        if not path.exists(filename):
            raise TemplateNotFound(name)
        f = codecs.open(filename, 'r', environment.template_charset)
        try:
            return f.read()
        finally:
            f.close()

The functions load and parse which are a requirement for a loader are added automatically by the BaseLoader.

Additionally to the BaseLoader there is a mixin class called CachedLoaderMixin that implements memory and disk caching of templates. Note that you have to give it a higher priority in the MRO than the BaseLoader which means that's the first base class when inheriting from it:

import codecs
from os.path import join, getmtime, exists
from jinja.loaders import BaseLoaderCachedLoaderMixin
from jinja.exceptions import TemplateNotFound

class CachedLoader(CachedLoaderMixin, BaseLoader):

    def __init__(self, path):
        self.path = path
        CachedLoaderMixin.__init__(
            True,       # use memory caching
            40,         # for up to 40 templates
            '/tmp',     # additionally save the compiled templates in /tmp
            True        # and reload cached templates automatically if changed
        )

    def get_source(self, environment, name, parent):
        filename = join(self.path, name)
        if not path.exists(filename):
            raise TemplateNotFound(name)
        f = codecs.open(filename, 'r', environment.template_charset)
        try:
            return f.read()
        finally:
            f.close()

    def check_source_changed(self, environment, name):
        fn = join(self.path, name)
        if exists(fn):
            return getmtime(fn)
        return -1

You don't have to provide the check_source_changed method. If it doesn't exist the option auto_reload won't have an effect. Also note that the check_source_changed method must not raise an exception if the template does not exist but return -1. The return value -1 is considered "always reload" whereas 0 means "do not reload".