~kkubasik/django/aggregation-branch

« back to all changes in this revision

Viewing changes to django/template/loader.py

  • Committer: adrian
  • Date: 2006-05-02 01:31:56 UTC
  • Revision ID: vcs-imports@canonical.com-20060502013156-2941fcd40d080649
MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Wrapper for loading templates from storage of some sort (e.g. filesystem, database).
 
2
#
 
3
# This uses the TEMPLATE_LOADERS setting, which is a list of loaders to use.
 
4
# Each loader is expected to have this interface:
 
5
#
 
6
#    callable(name, dirs=[])
 
7
#
 
8
# name is the template name.
 
9
# dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
 
10
#
 
11
# The loader should return a tuple of (template_source, path). The path returned
 
12
# might be shown to the user for debugging purposes, so it should identify where
 
13
# the template was loaded from.
 
14
#
 
15
# Each loader should have an "is_usable" attribute set. This is a boolean that
 
16
# specifies whether the loader can be used in this Python installation. Each
 
17
# loader is responsible for setting this when it's initialized.
 
18
#
 
19
# For example, the eggs loader (which is capable of loading templates from
 
20
# Python eggs) sets is_usable to False if the "pkg_resources" module isn't
 
21
# installed, because pkg_resources is necessary to read eggs.
 
22
 
 
23
from django.core.exceptions import ImproperlyConfigured
 
24
from django.template import Origin, StringOrigin, Template, Context, TemplateDoesNotExist, add_to_builtins
 
25
from django.conf import settings
 
26
 
 
27
template_source_loaders = None
 
28
 
 
29
class LoaderOrigin(Origin):
 
30
    def __init__(self, display_name, loader, name, dirs):
 
31
        super(LoaderOrigin, self).__init__(display_name)
 
32
        self.loader, self.loadname, self.dirs = loader, name, dirs
 
33
 
 
34
    def reload(self):
 
35
        return self.loader(self.loadname, self.dirs)[0]
 
36
 
 
37
def make_origin(display_name, loader, name, dirs):
 
38
    if settings.TEMPLATE_DEBUG:
 
39
        return LoaderOrigin(display_name, loader, name, dirs)
 
40
    else:
 
41
        return None
 
42
 
 
43
def find_template_source(name, dirs=None):
 
44
    # Calculate template_source_loaders the first time the function is executed
 
45
    # because putting this logic in the module-level namespace may cause
 
46
    # circular import errors. See Django ticket #1292.
 
47
    global template_source_loaders
 
48
    if template_source_loaders is None:
 
49
        template_source_loaders = []
 
50
        for path in settings.TEMPLATE_LOADERS:
 
51
            i = path.rfind('.')
 
52
            module, attr = path[:i], path[i+1:]
 
53
            try:
 
54
                mod = __import__(module, globals(), locals(), [attr])
 
55
            except ImportError, e:
 
56
                raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e)
 
57
            try:
 
58
                func = getattr(mod, attr)
 
59
            except AttributeError:
 
60
                raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable template source loader' % (module, attr)
 
61
            if not func.is_usable:
 
62
                import warnings
 
63
                warnings.warn("Your TEMPLATE_LOADERS setting includes %r, but your Python installation doesn't support that type of template loading. Consider removing that line from TEMPLATE_LOADERS." % path)
 
64
            else:
 
65
                template_source_loaders.append(func)
 
66
    for loader in template_source_loaders:
 
67
        try:
 
68
            source, display_name = loader(name, dirs)
 
69
            return (source, make_origin(display_name, loader, name, dirs))
 
70
        except TemplateDoesNotExist:
 
71
            pass
 
72
    raise TemplateDoesNotExist, name
 
73
 
 
74
def get_template(template_name):
 
75
    """
 
76
    Returns a compiled Template object for the given template name,
 
77
    handling template inheritance recursively.
 
78
    """
 
79
    return get_template_from_string(*find_template_source(template_name))
 
80
 
 
81
def get_template_from_string(source, origin=None):
 
82
    """
 
83
    Returns a compiled Template object for the given template code,
 
84
    handling template inheritance recursively.
 
85
    """
 
86
    return Template(source, origin)
 
87
 
 
88
def render_to_string(template_name, dictionary=None, context_instance=None):
 
89
    """
 
90
    Loads the given template_name and renders it with the given dictionary as
 
91
    context. The template_name may be a string to load a single template using
 
92
    get_template, or it may be a tuple to use select_template to find one of
 
93
    the templates in the list. Returns a string.
 
94
    """
 
95
    dictionary = dictionary or {}
 
96
    if isinstance(template_name, (list, tuple)):
 
97
        t = select_template(template_name)
 
98
    else:
 
99
        t = get_template(template_name)
 
100
    if context_instance:
 
101
        context_instance.update(dictionary)
 
102
    else:
 
103
        context_instance = Context(dictionary)
 
104
    return t.render(context_instance)
 
105
 
 
106
def select_template(template_name_list):
 
107
    "Given a list of template names, returns the first that can be loaded."
 
108
    for template_name in template_name_list:
 
109
        try:
 
110
            return get_template(template_name)
 
111
        except TemplateDoesNotExist:
 
112
            continue
 
113
    # If we get here, none of the templates could be loaded
 
114
    raise TemplateDoesNotExist, ', '.join(template_name_list)
 
115
 
 
116
add_to_builtins('django.template.loader_tags')