Ticket #3544: 3544.contexttemplatecache.2.diff

File 3544.contexttemplatecache.2.diff, 10.5 KB (added by emulbreh, 7 years ago)
  • django/template/__init__.py

     
    196196            ({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block', TOKEN_COMMENT: 'Comment'}[self.token_type],
    197197            self.contents[:20].replace('\n', ''))
    198198
    199     def split_contents(self):
    200         return list(smart_split(self.contents))
     199    def split_contents(self, yield_comma=False):
     200        return list(smart_split(self.contents, yield_comma=yield_comma))
    201201
    202202class Lexer(object):
    203203    def __init__(self, template_string, origin):
     
    898898                    dict = func(*args)
    899899
    900900                    if not getattr(self, 'nodelist', False):
    901                         from django.template.loader import get_template, select_template
    902901                        if not isinstance(file_name, basestring) and is_iterable(file_name):
    903                             t = select_template(file_name)
     902                            t = context.select_template(file_name)
    904903                        else:
    905                             t = get_template(file_name)
     904                            t = context.get_template(file_name)
    906905                        self.nodelist = t.nodelist
    907906                    return self.nodelist.render(context_class(dict,
    908907                            autoescape=context.autoescape))
     
    927926            raise InvalidTemplateLibrary("Template library %s does not have a variable named 'register'" % module_name)
    928927    return lib
    929928
     929def render_with_context_map(renderable, context_map, context):
     930    dict = {}
     931    for name in context_map:
     932        dict[name] = context_map[name].resolve(context)
     933    context.update(dict)
     934    output = renderable.render(context)
     935    context.pop()
     936    return output
     937
     938
    930939def add_to_builtins(module_name):
    931940    builtins.append(get_library(module_name))
    932941
  • django/template/defaulttags.py

     
    1111from django.template import Node, NodeList, Template, Context, Variable
    1212from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END
    1313from django.template import get_library, Library, InvalidTemplateLibrary
     14from django.template import render_with_context_map
    1415from django.conf import settings
    1516from django.utils.encoding import smart_str, smart_unicode
    1617from django.utils.itercompat import groupby
     
    390391        return str(int(round(ratio)))
    391392
    392393class WithNode(Node):
    393     def __init__(self, var, name, nodelist):
    394         self.var = var
    395         self.name = name
     394    def __init__(self, context_map, nodelist):
     395        self.context_map = context_map
    396396        self.nodelist = nodelist
    397397
    398398    def __repr__(self):
    399399        return "<WithNode>"
    400400
    401401    def render(self, context):
    402         val = self.var.resolve(context)
    403         context.push()
    404         context[self.name] = val
    405         output = self.nodelist.render(context)
    406         context.pop()
    407         return output
     402        return render_with_context_map(self.nodelist, self.context_map, context)
    408403
    409404#@register.tag
    410405def autoescape(parser, token):
     
    10911086            {{ total }} object{{ total|pluralize }}
    10921087        {% endwith %}
    10931088    """
    1094     bits = list(token.split_contents())
    1095     if len(bits) != 4 or bits[2] != "as":
    1096         raise TemplateSyntaxError("%r expected format is 'value as name'" %
     1089    bits = list(token.split_contents(yield_comma=True))
     1090
     1091    context_map = {}
     1092    syntax_error = False
     1093    if len(bits) % 4 == 0:
     1094        for i in range(len(bits)/4):
     1095                and_, value, as_, name = bits[4*i:4*(i+1)]
     1096                if i != 0 and and_ not in ('and', ',') or as_ != 'as':
     1097                        syntax_error = True
     1098                context_map[name] = parser.compile_filter(value)
     1099    else:
     1100        syntax_error = True
     1101
     1102    if syntax_error:
     1103        raise TemplateSyntaxError("%r expected format is 'value as name (and value as name)*'" %
    10971104                                  bits[0])
    1098     var = parser.compile_filter(bits[1])
    1099     name = bits[3]
    11001105    nodelist = parser.parse(('endwith',))
    11011106    parser.delete_first_token()
    1102     return WithNode(var, name, nodelist)
     1107    return WithNode(context_map, nodelist)
    11031108do_with = register.tag('with', do_with)
  • django/template/context.py

     
    99
    1010class Context(object):
    1111    "A stack container for variable context"
    12     def __init__(self, dict_=None, autoescape=True):
     12    def __init__(self, dict_=None, autoescape=True, loader=None):
    1313        dict_ = dict_ or {}
    1414        self.dicts = [dict_]
    1515        self.autoescape = autoescape
     16        self.template_cache = {}
     17        self.loader = loader
    1618
    1719    def __repr__(self):
    1820        return repr(self.dicts)
     
    6567        self.dicts = [other_dict] + self.dicts
    6668        return other_dict
    6769
     70    def get_template(self, template_name):
     71        if not template_name in self.template_cache:
     72            if self.loader is None:
     73                from django.template import loader
     74                tpl = loader.get_template(template_name)
     75            else:
     76                tpl = self.loader.get_template(template_name)
     77            self.template_cache[template_name] = tpl
     78        return self.template_cache[template_name]
     79
     80    def select_template(self, template_name_list):
     81        from django.template import TemplateDoesNotExist
     82        for template_name in template_name_list:
     83            try:
     84                return self.get_template(template_name)
     85            except TemplateDoesNotExist:
     86                continue
     87        raise TemplateDoesNotExist, ', '.join(template_name_list)
     88
    6889# This is a function rather than module-level procedural code because we only
    6990# want it to execute if somebody uses RequestContext.
    7091def get_standard_processors():
     
    93114    Additional processors can be specified as a list of callables
    94115    using the "processors" keyword argument.
    95116    """
    96     def __init__(self, request, dict=None, processors=None):
    97         Context.__init__(self, dict)
     117    def __init__(self, request, dict=None, processors=None, loader=None):
     118        Context.__init__(self, dict, loader=loader)
    98119        if processors is None:
    99120            processors = ()
    100121        else:
  • django/template/loader_tags.py

     
    3939class ExtendsNode(Node):
    4040    must_be_first = True
    4141
    42     def __init__(self, nodelist, parent_name, parent_name_expr, template_dirs=None):
     42    def __init__(self, nodelist, parent_name, parent_name_expr):
    4343        self.nodelist = nodelist
    4444        self.parent_name, self.parent_name_expr = parent_name, parent_name_expr
    45         self.template_dirs = template_dirs
    4645
    4746    def __repr__(self):
    4847        if self.parent_name_expr:
     
    6160        if hasattr(parent, 'render'):
    6261            return parent # parent is a Template object
    6362        try:
    64             source, origin = find_template_source(parent, self.template_dirs)
     63            return context.get_template(parent)
    6564        except TemplateDoesNotExist:
    6665            raise TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent
    67         else:
    68             return get_template_from_string(source, origin, parent)
    6966
    7067    def render(self, context):
    7168        compiled_parent = self.get_parent(context)
     
    9289                parent_block.nodelist = block_node.nodelist
    9390        return compiled_parent.render(context)
    9491
    95 class ConstantIncludeNode(Node):
    96     def __init__(self, template_path):
    97         try:
    98             t = get_template(template_path)
    99             self.template = t
    100         except:
    101             if settings.TEMPLATE_DEBUG:
    102                 raise
    103             self.template = None
    104 
    105     def render(self, context):
    106         if self.template:
    107             return self.template.render(context)
    108         else:
    109             return ''
    110 
    11192class IncludeNode(Node):
    11293    def __init__(self, template_name):
    11394        self.template_name = Variable(template_name)
     
    11596    def render(self, context):
    11697        try:
    11798            template_name = self.template_name.resolve(context)
    118             t = get_template(template_name)
    119             return t.render(context)
     99            tpl = context.get_template(template_name)
     100            return tpl.render(context)
    120101        except TemplateSyntaxError, e:
    121102            if settings.TEMPLATE_DEBUG:
    122103                raise
     
    178159    bits = token.contents.split()
    179160    if len(bits) != 2:
    180161        raise TemplateSyntaxError, "%r tag takes one argument: the name of the template to be included" % bits[0]
    181     path = bits[1]
    182     if path[0] in ('"', "'") and path[-1] == path[0]:
    183         return ConstantIncludeNode(path[1:-1])
    184162    return IncludeNode(bits[1])
    185163
    186164register.tag('block', do_block)
  • django/utils/text.py

     
    196196    return str(ustring_re.sub(fix, s))
    197197javascript_quote = allow_lazy(javascript_quote, unicode)
    198198
    199 smart_split_re = re.compile('("(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'|[^\\s]+)')
    200 def smart_split(text):
     199quoted_string_pattern = '"(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\''
     200smart_split_re = re.compile('(%s|[^\\s]+)' % quoted_string_pattern)
     201smart_split_comma_re = re.compile('(%s|[^\\s,]+|,)' % quoted_string_pattern)
     202def smart_split(text, yield_comma=False):
    201203    r"""
    202204    Generator that splits a string by spaces, leaving quoted phrases together.
    203205    Supports both single and double quotes, and supports escaping quotes with
     
    212214        [u'A', u'""funky" style"', u'test.']
    213215    """
    214216    text = force_unicode(text)
    215     for bit in smart_split_re.finditer(text):
     217    regexp = yield_comma and smart_split_comma_re or smart_split_re
     218    for bit in regexp.finditer(text):
    216219        bit = bit.group(0)
    217220        if bit[0] == '"' and bit[-1] == '"':
    218221            yield '"' + bit[1:-1].replace('\\"', '"').replace('\\\\', '\\') + '"'
Back to Top