makoloader.py 3.45 KB
Newer Older
1
import logging
2

3
from django.conf import settings
4
from django.core.exceptions import ImproperlyConfigured
5 6 7
from django.template.base import TemplateDoesNotExist
from django.template.loaders.filesystem import Loader as FilesystemLoader
from django.template.loaders.app_directories import Loader as AppDirectoriesLoader
8
from django.template import Engine
9

David Baumgold committed
10
from edxmako.template import Template
11

12
from openedx.core.lib.tempdir import mkdtemp_clean
13 14

log = logging.getLogger(__name__)
15

Calen Pennington committed
16

17 18 19 20 21
class MakoLoader(object):
    """
    This is a Django loader object which will load the template as a
    Mako template if the first line is "## mako". It is based off BaseLoader
    in django.template.loader.
22
    We need this in order to be able to include mako templates inside main_django.html.
23
    """
Calen Pennington committed
24

25 26 27 28 29
    is_usable = False

    def __init__(self, base_loader):
        # base_loader is an instance of a BaseLoader subclass
        self.base_loader = base_loader
Calen Pennington committed
30

31
        module_directory = getattr(settings, 'MAKO_MODULE_DIR', None)
Calen Pennington committed
32

33 34
        if module_directory is None:
            log.warning("For more caching of mako templates, set the MAKO_MODULE_DIR in settings!")
35
            module_directory = mkdtemp_clean()
Calen Pennington committed
36

37
        self.module_directory = module_directory
Calen Pennington committed
38

39 40 41 42
    def __call__(self, template_name, template_dirs=None):
        return self.load_template(template_name, template_dirs)

    def load_template(self, template_name, template_dirs=None):
43
        source, file_path = self.load_template_source(template_name, template_dirs)
Calen Pennington committed
44

45 46
        if source.startswith("## mako\n"):
            # This is a mako template
47 48 49 50
            template = Template(filename=file_path,
                                module_directory=self.module_directory,
                                input_encoding='utf-8',
                                output_encoding='utf-8',
51 52
                                default_filters=['decode.utf8'],
                                encoding_errors='replace',
53
                                uri=template_name)
54 55 56 57
            return template, None
        else:
            # This is a regular template
            try:
58
                template = Engine.get_default().from_string(source)
59
                return template, None
60 61 62 63
            except ImproperlyConfigured:
                # Either no DjangoTemplates engine was configured -or- multiple engines
                # were configured, making the get_default() call above fail.
                raise
64
            except TemplateDoesNotExist:
65 66 67
                # If compiling the loaded template raises TemplateDoesNotExist, back off to
                # returning the source and display name for the requested template.
                # This allows for eventual correct identification of the actual template that does
68
                # not exist.
69
                return source, file_path
Calen Pennington committed
70

71
    def load_template_source(self, template_name, template_dirs=None):
72
        # Just having this makes the template load as an instance, instead of a class.
73
        return self.base_loader.load_template_source(template_name, template_dirs)
74 75 76

    def reset(self):
        self.base_loader.reset()
Calen Pennington committed
77

78 79 80

class MakoFilesystemLoader(MakoLoader):
    is_usable = True
81
    _accepts_engine_in_init = True
Calen Pennington committed
82

83 84
    def __init__(self, *args):
        MakoLoader.__init__(self, FilesystemLoader(*args))
Calen Pennington committed
85 86


87 88
class MakoAppDirectoriesLoader(MakoLoader):
    is_usable = True
89
    _accepts_engine_in_init = True
Calen Pennington committed
90

91 92
    def __init__(self, *args):
        MakoLoader.__init__(self, AppDirectoriesLoader(*args))