Ticket #6262: cache_templates.4.diff

File cache_templates.4.diff, 32.4 KB (added by Michael Malone, 15 years ago)
  • django/test/utils.py

     
    5454        - Diverting the email sending functions to a test buffer
    5555        - Setting the active locale to match the LANGUAGE_CODE setting.
    5656    """
    57     Template.original_render = Template.render
    58     Template.render = instrumented_test_render
     57    Template.original_render = Template._render
     58    Template._render = instrumented_test_render
    5959
    6060    mail.original_SMTPConnection = mail.SMTPConnection
    6161    mail.SMTPConnection = TestSMTPConnection
     
    7171        - Restoring the email sending functions
    7272
    7373    """
    74     Template.render = Template.original_render
     74    Template._render = Template.original_render
    7575    del Template.original_render
    7676
    7777    mail.SMTPConnection = mail.original_SMTPConnection
  • django/template/__init__.py

     
    173173            for subnode in node:
    174174                yield subnode
    175175
    176     def render(self, context):
    177         "Display stage -- can be called many times"
     176    def _render(self, context):
    178177        return self.nodelist.render(context)
    179178
     179    def render(self, context, push_parser_context=True):
     180        "Display stage -- can be called many times"
     181        context.parser_context.push()
     182        try:
     183            return self._render(context)
     184        finally:
     185            context.parser_context.pop()
     186
    180187def compile_string(template_string, origin):
    181188    "Compiles template_string into NodeList ready for rendering"
    182189    if settings.TEMPLATE_DEBUG:
  • django/template/loaders/app_directories.py

     
    99from django.conf import settings
    1010from django.core.exceptions import ImproperlyConfigured
    1111from django.template import TemplateDoesNotExist
     12from django.template.loader import BaseLoader
    1213from django.utils._os import safe_join
    1314from django.utils.importlib import import_module
    1415
     
    2728# It won't change, so convert it to a tuple to save memory.
    2829app_template_dirs = tuple(app_template_dirs)
    2930
    30 def get_template_sources(template_name, template_dirs=None):
    31     """
    32     Returns the absolute paths to "template_name", when appended to each
    33     directory in "template_dirs". Any paths that don't lie inside one of the
    34     template dirs are excluded from the result set, for security reasons.
    35     """
    36     if not template_dirs:
    37         template_dirs = app_template_dirs
    38     for template_dir in template_dirs:
    39         try:
    40             yield safe_join(template_dir, template_name)
    41         except UnicodeDecodeError:
    42             # The template dir name was a bytestring that wasn't valid UTF-8.
    43             raise
    44         except ValueError:
    45             # The joined path was located outside of template_dir.
    46             pass
     31class Loader(BaseLoader):
     32    is_usable = True
    4733
     34    def get_template_sources(self, template_name, template_dirs=None):
     35        """
     36        Returns the absolute paths to "template_name", when appended to each
     37        directory in "template_dirs". Any paths that don't lie inside one of the
     38        template dirs are excluded from the result set, for security reasons.
     39        """
     40        if not template_dirs:
     41            template_dirs = app_template_dirs
     42        for template_dir in template_dirs:
     43            try:
     44                yield safe_join(template_dir, template_name)
     45            except UnicodeDecodeError:
     46                # The template dir name was a bytestring that wasn't valid UTF-8.
     47                raise
     48            except ValueError:
     49                # The joined path was located outside of template_dir.
     50                pass
     51
     52    def load_template_source(self, template_name, template_dirs=None):
     53        for filepath in self.get_template_sources(template_name, template_dirs):
     54            try:
     55                return (open(filepath).read().decode(settings.FILE_CHARSET), filepath)
     56            except IOError:
     57                pass
     58        raise TemplateDoesNotExist, template_name
     59
     60loader = Loader()
     61
    4862def load_template_source(template_name, template_dirs=None):
    49     for filepath in get_template_sources(template_name, template_dirs):
    50         try:
    51             return (open(filepath).read().decode(settings.FILE_CHARSET), filepath)
    52         except IOError:
    53             pass
    54     raise TemplateDoesNotExist, template_name
     63    # For backwards compatibility
     64    return loader.load_template_source(template_name, template_dirs)
    5565load_template_source.is_usable = True
  • django/template/loaders/filesystem.py

     
    44
    55from django.conf import settings
    66from django.template import TemplateDoesNotExist
     7from django.template.loader import BaseLoader
    78from django.utils._os import safe_join
    89
    9 def get_template_sources(template_name, template_dirs=None):
    10     """
    11     Returns the absolute paths to "template_name", when appended to each
    12     directory in "template_dirs". Any paths that don't lie inside one of the
    13     template dirs are excluded from the result set, for security reasons.
    14     """
    15     if not template_dirs:
    16         template_dirs = settings.TEMPLATE_DIRS
    17     for template_dir in template_dirs:
    18         try:
    19             yield safe_join(template_dir, template_name)
    20         except UnicodeDecodeError:
    21             # The template dir name was a bytestring that wasn't valid UTF-8.
    22             raise
    23         except ValueError:
    24             # The joined path was located outside of this particular
    25             # template_dir (it might be inside another one, so this isn't
    26             # fatal).
    27             pass
     10class Loader(BaseLoader):
     11    is_usable = True
    2812
     13    def get_template_sources(self, template_name, template_dirs=None):
     14        """
     15        Returns the absolute paths to "template_name", when appended to each
     16        directory in "template_dirs". Any paths that don't lie inside one of the
     17        template dirs are excluded from the result set, for security reasons.
     18        """
     19        if not template_dirs:
     20            template_dirs = settings.TEMPLATE_DIRS
     21        for template_dir in template_dirs:
     22            try:
     23                yield safe_join(template_dir, template_name)
     24            except UnicodeDecodeError:
     25                # The template dir name was a bytestring that wasn't valid UTF-8.
     26                raise
     27            except ValueError:
     28                # The joined path was located outside of this particular
     29                # template_dir (it might be inside another one, so this isn't
     30                # fatal).
     31                pass
     32
     33    def load_template_source(self, template_name, template_dirs=None):
     34        tried = []
     35        for filepath in self.get_template_sources(template_name, template_dirs):
     36            try:
     37                return (open(filepath).read().decode(settings.FILE_CHARSET), filepath)
     38            except IOError:
     39                tried.append(filepath)
     40        if tried:
     41            error_msg = "Tried %s" % tried
     42        else:
     43            error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
     44        raise TemplateDoesNotExist, error_msg
     45    load_template_source.is_usable = True
     46
     47loader = Loader()
     48
    2949def load_template_source(template_name, template_dirs=None):
    30     tried = []
    31     for filepath in get_template_sources(template_name, template_dirs):
    32         try:
    33             return (open(filepath).read().decode(settings.FILE_CHARSET), filepath)
    34         except IOError:
    35             tried.append(filepath)
    36     if tried:
    37         error_msg = "Tried %s" % tried
    38     else:
    39         error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
    40     raise TemplateDoesNotExist, error_msg
     50    # For backwards compatibility
     51    return loader.load_template_source(template_name, template_dirs)
    4152load_template_source.is_usable = True
  • django/template/loaders/eggs.py

     
    66    resource_string = None
    77
    88from django.template import TemplateDoesNotExist
     9from django.template.loader import BaseLoader
    910from django.conf import settings
    1011
     12class Loader(BaseLoader):
     13    is_usable = resource_string is not None
     14
     15    def load_template_source(self, template_name, template_dirs=None):
     16        """
     17        Loads templates from Python eggs via pkg_resource.resource_string.
     18
     19        For every installed app, it tries to get the resource (app, template_name).
     20        """
     21        if resource_string is not None:
     22            pkg_name = 'templates/' + template_name
     23            for app in settings.INSTALLED_APPS:
     24                try:
     25                    return (resource_string(app, pkg_name).decode(settings.FILE_CHARSET), 'egg:%s:%s' % (app, pkg_name))
     26                except:
     27                    pass
     28        raise TemplateDoesNotExist, template_name
     29
     30loader = Loader()
     31
    1132def load_template_source(template_name, template_dirs=None):
    12     """
    13     Loads templates from Python eggs via pkg_resource.resource_string.
    14 
    15     For every installed app, it tries to get the resource (app, template_name).
    16     """
    17     if resource_string is not None:
    18         pkg_name = 'templates/' + template_name
    19         for app in settings.INSTALLED_APPS:
    20             try:
    21                 return (resource_string(app, pkg_name).decode(settings.FILE_CHARSET), 'egg:%s:%s' % (app, pkg_name))
    22             except:
    23                 pass
    24     raise TemplateDoesNotExist, template_name
     33    return loader.load_template_source(template_name, template_dirs)
    2534load_template_source.is_usable = resource_string is not None
  • django/template/loaders/cached.py

     
     1"""
     2Wrapper class that takes a list of template loaders as an argument and attempts
     3to load templates from them in order, caching the result.
     4"""
     5
     6from django.template import TemplateDoesNotExist
     7from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin
     8from django.utils.importlib import import_module
     9from django.core.exceptions import ImproperlyConfigured
     10
     11class Loader(BaseLoader):
     12    is_usable = True
     13    template_cache = {}
     14
     15    def __init__(self, loaders):
     16        self._loaders = loaders
     17        self._cached_loaders = []
     18
     19    @property
     20    def loaders(self):
     21        # Resolve loaders on demand to avoid circular imports
     22        if not self._cached_loaders:
     23            for loader in self._loaders:
     24                self._cached_loaders.append(find_template_loader(loader))
     25        return self._cached_loaders
     26
     27    def find_template(self, name, dirs=None):
     28        for loader in self.loaders:
     29            try:
     30                template, display_name = loader(name, dirs)
     31                return (template, make_origin(display_name, loader, name, dirs))
     32            except TemplateDoesNotExist:
     33                pass
     34        raise TemplateDoesNotExist, name
     35
     36    def load_template(self, template_name, template_dirs=None):
     37        if template_name not in self.template_cache:
     38            template, origin = self.find_template(template_name, template_dirs)
     39            if not hasattr(template, 'render'):
     40                template = get_template_from_string(template, origin, template_name)
     41            self.template_cache[template_name] = (template, origin)
     42        return self.template_cache[template_name]
     43
     44    def reset(self):
     45        "Empty the template cache."
     46        self.template_cache = {}
  • django/template/defaulttags.py

     
    3939
    4040class CycleNode(Node):
    4141    def __init__(self, cyclevars, variable_name=None):
    42         self.cycle_iter = itertools_cycle(cyclevars)
     42        self.cyclevars = cyclevars
    4343        self.variable_name = variable_name
    4444
    4545    def render(self, context):
    46         value = self.cycle_iter.next().resolve(context)
     46        if self not in context.parser_context:
     47            context.parser_context[self] = {'cycle_iter': itertools_cycle(self.cyclevars)}
     48        cycle_iter = context.parser_context[self]['cycle_iter']
     49        value = cycle_iter.next().resolve(context)
    4750        if self.variable_name:
    4851            context[self.variable_name] = value
    4952        return value
  • django/template/context.py

     
    77    "pop() has been called more times than push()"
    88    pass
    99
    10 class Context(object):
    11     "A stack container for variable context"
    12     def __init__(self, dict_=None, autoescape=True, current_app=None):
     10class BaseContext(object):
     11    def __init__(self, dict_=None):
    1312        dict_ = dict_ or {}
    1413        self.dicts = [dict_]
    15         self.autoescape = autoescape
    16         self.current_app = current_app
    1714
    1815    def __repr__(self):
    1916        return repr(self.dicts)
    2017
    2118    def __iter__(self):
    22         for d in self.dicts:
     19        for d in reversed(self.dicts):
    2320            yield d
    24 
     21   
    2522    def push(self):
    2623        d = {}
    27         self.dicts = [d] + self.dicts
     24        self.dicts.append(d)
    2825        return d
    2926
    3027    def pop(self):
    3128        if len(self.dicts) == 1:
    3229            raise ContextPopException
    33         return self.dicts.pop(0)
     30        return self.dicts.pop()
    3431
    3532    def __setitem__(self, key, value):
    3633        "Set a variable in the current context"
    37         self.dicts[0][key] = value
     34        self.dicts[-1][key] = value
    3835
    3936    def __getitem__(self, key):
    4037        "Get a variable's value, starting at the current context and going upward"
    41         for d in self.dicts:
     38        for d in reversed(self.dicts):
    4239            if key in d:
    4340                return d[key]
    4441        raise KeyError(key)
    4542
    4643    def __delitem__(self, key):
    4744        "Delete a variable from the current context"
    48         del self.dicts[0][key]
     45        del self.dicts[-1][key]
    4946
    5047    def has_key(self, key):
    5148        for d in self.dicts:
     
    5350                return True
    5451        return False
    5552
    56     __contains__ = has_key
     53    def __contains__(self, key):
     54        return self.has_key(key)
    5755
    5856    def get(self, key, otherwise=None):
    5957        for d in self.dicts:
     
    6159                return d[key]
    6260        return otherwise
    6361
     62
     63class Context(BaseContext):
     64    "A stack container for variable context"
     65    def __init__(self, dict_=None, autoescape=True, current_app=None):
     66        self.autoescape = autoescape
     67        self.current_app = current_app
     68        self.parser_context = ParserContext()
     69        super(Context, self).__init__(dict_)
     70
    6471    def update(self, other_dict):
    6572        "Like dict.update(). Pushes an entire dictionary's keys and values onto the context."
    6673        if not hasattr(other_dict, '__getitem__'):
    6774            raise TypeError('other_dict must be a mapping (dictionary-like) object.')
    68         self.dicts = [other_dict] + self.dicts
     75        self.dicts.append(other_dict)
    6976        return other_dict
    7077
     78class ParserContext(BaseContext):
     79    """A stack container for storing Template state."""
     80    def __iter__(self):
     81        for d in self.dicts[-1]:
     82            yield d
     83
     84    def has_key(self, key):
     85        return key in self.dicts[-1]
     86
     87    def get(self, key, otherwise=None):
     88        d = self.dicts[-1]
     89        if key in d:
     90            return d[key]
     91        return otherwise
     92
    7193# This is a function rather than module-level procedural code because we only
    7294# want it to execute if somebody uses RequestContext.
    7395def get_standard_processors():
  • django/template/loader_tags.py

     
    11from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable
    22from django.template import Library, Node, TextNode
    3 from django.template.loader import get_template, get_template_from_string, find_template_source
     3from django.template.loader import get_template
    44from django.conf import settings
    55from django.utils.safestring import mark_safe
    66
    77register = Library()
    88
     9BLOCK_CONTEXT_KEY = 'block_context'
     10
    911class ExtendsError(Exception):
    1012    pass
    1113
     14class BlockContext(object):
     15    def __init__(self):
     16        # Dictionary of FIFO queues.
     17        self.blocks = {}
     18
     19    def add_blocks(self, blocks):
     20        for name, block in blocks.iteritems():
     21            if name in self.blocks:
     22                self.blocks[name].insert(0, block)
     23            else:
     24                self.blocks[name] = [block]
     25
     26    def pop(self, name):
     27        try:
     28            return self.blocks[name].pop()
     29        except (IndexError, KeyError):
     30            return None
     31
     32    def push(self, name, block):
     33        self.blocks[name].append(block)
     34
     35    def get_block(self, name):
     36        try:
     37            return self.blocks[name][-1]
     38        except (IndexError, KeyError):
     39            return None
     40
    1241class BlockNode(Node):
    1342    def __init__(self, name, nodelist, parent=None):
    1443        self.name, self.nodelist, self.parent = name, nodelist, parent
     
    1746        return "<Block Node: %s. Contents: %r>" % (self.name, self.nodelist)
    1847
    1948    def render(self, context):
     49        block_context = context.parser_context.get(BLOCK_CONTEXT_KEY, None)
    2050        context.push()
    21         # Save context in case of block.super().
    22         self.context = context
    23         context['block'] = self
    24         result = self.nodelist.render(context)
     51        if block_context is None:
     52            context['block'] = self
     53            result = self.nodelist.render(context)
     54        else:
     55            push = block = block_context.pop(self.name)
     56            if block is None:
     57                block = self
     58            # Create new block so we can store context without thread-safety issues.
     59            block = BlockNode(block.name, block.nodelist)
     60            block.context = context
     61            context['block'] = block
     62            result = block.nodelist.render(context)
     63            if push is not None:
     64                block_context.push(self.name, push)
    2565        context.pop()
    2666        return result
    2767
    2868    def super(self):
    29         if self.parent:
    30             return mark_safe(self.parent.render(self.context))
     69        parser_context = self.context.parser_context
     70        if (BLOCK_CONTEXT_KEY in parser_context and
     71            parser_context[BLOCK_CONTEXT_KEY].get_block(self.name) is not None):
     72            return mark_safe(self.render(self.context))
    3173        return ''
    3274
    33     def add_parent(self, nodelist):
    34         if self.parent:
    35             self.parent.add_parent(nodelist)
    36         else:
    37             self.parent = BlockNode(self.name, nodelist)
    38 
    3975class ExtendsNode(Node):
    4076    must_be_first = True
    4177
     
    4379        self.nodelist = nodelist
    4480        self.parent_name, self.parent_name_expr = parent_name, parent_name_expr
    4581        self.template_dirs = template_dirs
    46 
     82        self.blocks = dict([(n.name, n) for n in nodelist.get_nodes_by_type(BlockNode)])
     83 
    4784    def __repr__(self):
    4885        if self.parent_name_expr:
    4986            return "<ExtendsNode: extends %s>" % self.parent_name_expr.token
     
    6198        if hasattr(parent, 'render'):
    6299            return parent # parent is a Template object
    63100        try:
    64             source, origin = find_template_source(parent, self.template_dirs)
     101            return get_template(parent)
    65102        except TemplateDoesNotExist:
    66103            raise TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent
    67         else:
    68             return get_template_from_string(source, origin, parent)
    69104
    70105    def render(self, context):
    71106        compiled_parent = self.get_parent(context)
    72         parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)])
    73         for block_node in self.nodelist.get_nodes_by_type(BlockNode):
    74             # Check for a BlockNode with this node's name, and replace it if found.
    75             try:
    76                 parent_block = parent_blocks[block_node.name]
    77             except KeyError:
    78                 # This BlockNode wasn't found in the parent template, but the
    79                 # parent block might be defined in the parent's *parent*, so we
    80                 # add this BlockNode to the parent's ExtendsNode nodelist, so
    81                 # it'll be checked when the parent node's render() is called.
    82107
    83                 # Find out if the parent template has a parent itself
    84                 for node in compiled_parent.nodelist:
    85                     if not isinstance(node, TextNode):
    86                         # If the first non-text node is an extends, handle it.
    87                         if isinstance(node, ExtendsNode):
    88                             node.nodelist.append(block_node)
    89                         # Extends must be the first non-text node, so once you find
    90                         # the first non-text node you can stop looking.
    91                         break
    92             else:
    93                 # Keep any existing parents and add a new one. Used by BlockNode.
    94                 parent_block.parent = block_node.parent
    95                 parent_block.add_parent(parent_block.nodelist)
    96                 parent_block.nodelist = block_node.nodelist
    97         return compiled_parent.render(context)
     108        if BLOCK_CONTEXT_KEY not in context.parser_context:
     109            context.parser_context[BLOCK_CONTEXT_KEY] = BlockContext()
     110        block_context = context.parser_context[BLOCK_CONTEXT_KEY]
    98111
     112        # Add the block nodes from this node to the block context
     113        block_context.add_blocks(self.blocks)
     114
     115        # If this block's parent doesn't have an extends node it is the root,
     116        # and its block nodes also need to be added to the block context.
     117        for node in compiled_parent.nodelist:
     118            # The ExtendsNode has to be the first non-text node.
     119            if not isinstance(node, TextNode):
     120                if not isinstance(node, ExtendsNode):
     121                    blocks = dict([(n.name, n) for n in
     122                                   compiled_parent.nodelist.get_nodes_by_type(BlockNode)])
     123                    block_context.add_blocks(blocks)
     124                break
     125
     126        # Call Template._render explicitly so the parser context stays
     127        # the same.
     128        return compiled_parent._render(context)
     129
    99130class ConstantIncludeNode(Node):
    100131    def __init__(self, template_path):
    101132        try:
  • django/template/loader.py

     
    2727
    2828template_source_loaders = None
    2929
     30class BaseLoader(object):
     31    is_usable = False
     32
     33    def __call__(self, template_name, template_dirs=None):
     34        return self.load_template(template_name, template_dirs)
     35
     36    def load_template(self, template_name, template_dirs=None):
     37        source, origin = self.load_template_source(template_name, template_dirs)
     38        template = get_template_from_string(source, name=template_name)
     39        return template, origin
     40   
     41    def load_template_source(self, template_name, template_dirs=None):
     42        """
     43        Returns a tuple containing the source and origin for the given template
     44        name.
     45
     46        """
     47        raise NotImplementedError
     48
     49    def reset(self):
     50        """
     51        Resets any state maintained by the loader instance (e.g., cached
     52        templates or cached loader modules).
     53
     54        """
     55        pass
     56
    3057class LoaderOrigin(Origin):
    3158    def __init__(self, display_name, loader, name, dirs):
    3259        super(LoaderOrigin, self).__init__(display_name)
     
    4168    else:
    4269        return None
    4370
    44 def find_template_source(name, dirs=None):
     71def find_template_loader(loader):
     72    if callable(loader):
     73        return loader
     74    elif isinstance(loader, basestring):
     75        i = loader.rfind('.')
     76        module, attr = loader[:i], loader[i+1:]
     77        try:
     78            mod = import_module(module)
     79        except ImportError, e:
     80            raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e)
     81        try:
     82            func = getattr(mod, attr)
     83        except AttributeError:
     84            raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable template source loader' % (module, attr)
     85        if not func.is_usable:
     86            import warnings
     87            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." % loader)
     88        else:
     89            return func
     90    else:
     91        raise ImproperlyConfigured, 'Loader does not define a "load_template" callable template source loader'
     92
     93def find_template(name, dirs=None):
    4594    # Calculate template_source_loaders the first time the function is executed
    4695    # because putting this logic in the module-level namespace may cause
    4796    # circular import errors. See Django ticket #1292.
    4897    global template_source_loaders
    4998    if template_source_loaders is None:
    5099        loaders = []
    51         for path in settings.TEMPLATE_LOADERS:
    52             i = path.rfind('.')
    53             module, attr = path[:i], path[i+1:]
    54             try:
    55                 mod = import_module(module)
    56             except ImportError, e:
    57                 raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e)
    58             try:
    59                 func = getattr(mod, attr)
    60             except AttributeError:
    61                 raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable template source loader' % (module, attr)
    62             if not func.is_usable:
    63                 import warnings
    64                 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)
    65             else:
    66                 loaders.append(func)
     100        for loader in settings.TEMPLATE_LOADERS:
     101            loaders.append(find_template_loader(loader))
    67102        template_source_loaders = tuple(loaders)
    68103    for loader in template_source_loaders:
    69104        try:
     
    78113    Returns a compiled Template object for the given template name,
    79114    handling template inheritance recursively.
    80115    """
    81     source, origin = find_template_source(template_name)
    82     template = get_template_from_string(source, origin, template_name)
     116    template, origin = find_template(template_name)
     117    if not hasattr(template, 'render'):
     118        # template needs to be compiled
     119        template = get_template_from_string(template, origin, template_name)
    83120    return template
    84121
    85122def get_template_from_string(source, origin=None, name=None):
  • tests/regressiontests/test_client_regress/models.py

     
    1010from django.core.urlresolvers import reverse
    1111from django.core.exceptions import SuspiciousOperation
    1212from django.template import TemplateDoesNotExist, TemplateSyntaxError, Context
     13from django.template.loader import find_template_loader
    1314
    1415class AssertContainsTests(TestCase):
    1516    def setUp(self):
     
    436437
    437438class TemplateExceptionTests(TestCase):
    438439    def setUp(self):
     440        # Reset the loaders so they don't try to render cached templates.
     441        for loader in settings.TEMPLATE_LOADERS:
     442            loader = find_template_loader(loader)
     443            if hasattr(loader, 'reset'):
     444                loader.reset()
    439445        self.old_templates = settings.TEMPLATE_DIRS
    440446        settings.TEMPLATE_DIRS = ()
    441447
  • tests/regressiontests/templates/tests.py

     
    105105                # Fix expected sources so they are normcased and abspathed
    106106                expected_sources = [os.path.normcase(os.path.abspath(s)) for s in expected_sources]
    107107            # Test the two loaders (app_directores and filesystem).
    108             func1 = lambda p, t: list(app_directories.get_template_sources(p, t))
    109             func2 = lambda p, t: list(filesystem.get_template_sources(p, t))
     108            func1 = lambda p, t: list(app_directories.loader.get_template_sources(p, t))
     109            func2 = lambda p, t: list(filesystem.loader.get_template_sources(p, t))
    110110            for func in (func1, func2):
    111111                if isinstance(expected_sources, list):
    112112                    self.assertEqual(func(path, template_dirs), expected_sources)
     
    197197            except KeyError:
    198198                raise template.TemplateDoesNotExist, template_name
    199199
     200        from django.template.loaders.cached import Loader
     201        cache_loader = Loader((test_template_loader,))
     202
    200203        old_template_loaders = loader.template_source_loaders
    201         loader.template_source_loaders = [test_template_loader]
     204        loader.template_source_loaders = [cache_loader]
    202205
    203206        failures = []
    204207        tests = template_tests.items()
     
    231234            for invalid_str, result in [('', normal_string_result),
    232235                                        (expected_invalid_str, invalid_string_result)]:
    233236                settings.TEMPLATE_STRING_IF_INVALID = invalid_str
    234                 try:
    235                     test_template = loader.get_template(name)
    236                     output = self.render(test_template, vals)
    237                 except ContextStackException:
    238                     failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Context stack was left imbalanced" % (invalid_str, name))
    239                     continue
    240                 except Exception:
    241                     exc_type, exc_value, exc_tb = sys.exc_info()
    242                     if exc_type != result:
    243                         tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb))
    244                         failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s\n%s" % (invalid_str, name, exc_type, exc_value, tb))
    245                     continue
    246                 if output != result:
    247                     failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (invalid_str, name, result, output))
     237                for cached in (False, True):
     238                    try:
     239                        test_template = loader.get_template(name)
     240                        output = self.render(test_template, vals)
     241                    except ContextStackException:
     242                        failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Context stack was left imbalanced" % (cached, invalid_str, name))
     243                        continue
     244                    except Exception:
     245                        exc_type, exc_value, exc_tb = sys.exc_info()
     246                        if exc_type != result:
     247                            tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb))
     248                            failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s\n%s" % (cached, invalid_str, name, exc_type, exc_value, tb))
     249                        continue
     250                    if output != result:
     251                        failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (cached, invalid_str, name, result, output))
     252                cache_loader.reset()
    248253
    249254            if 'LANGUAGE_CODE' in vals[1]:
    250255                deactivate()
Back to Top