Ticket #3544: 3544.contexttemplatecache.2.diff
File 3544.contexttemplatecache.2.diff, 10.5 KB (added by , 16 years ago) |
---|
-
django/template/__init__.py
196 196 ({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block', TOKEN_COMMENT: 'Comment'}[self.token_type], 197 197 self.contents[:20].replace('\n', '')) 198 198 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)) 201 201 202 202 class Lexer(object): 203 203 def __init__(self, template_string, origin): … … 898 898 dict = func(*args) 899 899 900 900 if not getattr(self, 'nodelist', False): 901 from django.template.loader import get_template, select_template902 901 if not isinstance(file_name, basestring) and is_iterable(file_name): 903 t = select_template(file_name)902 t = context.select_template(file_name) 904 903 else: 905 t = get_template(file_name)904 t = context.get_template(file_name) 906 905 self.nodelist = t.nodelist 907 906 return self.nodelist.render(context_class(dict, 908 907 autoescape=context.autoescape)) … … 927 926 raise InvalidTemplateLibrary("Template library %s does not have a variable named 'register'" % module_name) 928 927 return lib 929 928 929 def 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 930 939 def add_to_builtins(module_name): 931 940 builtins.append(get_library(module_name)) 932 941 -
django/template/defaulttags.py
11 11 from django.template import Node, NodeList, Template, Context, Variable 12 12 from 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 13 13 from django.template import get_library, Library, InvalidTemplateLibrary 14 from django.template import render_with_context_map 14 15 from django.conf import settings 15 16 from django.utils.encoding import smart_str, smart_unicode 16 17 from django.utils.itercompat import groupby … … 390 391 return str(int(round(ratio))) 391 392 392 393 class 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 396 396 self.nodelist = nodelist 397 397 398 398 def __repr__(self): 399 399 return "<WithNode>" 400 400 401 401 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) 408 403 409 404 #@register.tag 410 405 def autoescape(parser, token): … … 1091 1086 {{ total }} object{{ total|pluralize }} 1092 1087 {% endwith %} 1093 1088 """ 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)*'" % 1097 1104 bits[0]) 1098 var = parser.compile_filter(bits[1])1099 name = bits[3]1100 1105 nodelist = parser.parse(('endwith',)) 1101 1106 parser.delete_first_token() 1102 return WithNode( var, name, nodelist)1107 return WithNode(context_map, nodelist) 1103 1108 do_with = register.tag('with', do_with) -
django/template/context.py
9 9 10 10 class Context(object): 11 11 "A stack container for variable context" 12 def __init__(self, dict_=None, autoescape=True ):12 def __init__(self, dict_=None, autoescape=True, loader=None): 13 13 dict_ = dict_ or {} 14 14 self.dicts = [dict_] 15 15 self.autoescape = autoescape 16 self.template_cache = {} 17 self.loader = loader 16 18 17 19 def __repr__(self): 18 20 return repr(self.dicts) … … 65 67 self.dicts = [other_dict] + self.dicts 66 68 return other_dict 67 69 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 68 89 # This is a function rather than module-level procedural code because we only 69 90 # want it to execute if somebody uses RequestContext. 70 91 def get_standard_processors(): … … 93 114 Additional processors can be specified as a list of callables 94 115 using the "processors" keyword argument. 95 116 """ 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) 98 119 if processors is None: 99 120 processors = () 100 121 else: -
django/template/loader_tags.py
39 39 class ExtendsNode(Node): 40 40 must_be_first = True 41 41 42 def __init__(self, nodelist, parent_name, parent_name_expr , template_dirs=None):42 def __init__(self, nodelist, parent_name, parent_name_expr): 43 43 self.nodelist = nodelist 44 44 self.parent_name, self.parent_name_expr = parent_name, parent_name_expr 45 self.template_dirs = template_dirs46 45 47 46 def __repr__(self): 48 47 if self.parent_name_expr: … … 61 60 if hasattr(parent, 'render'): 62 61 return parent # parent is a Template object 63 62 try: 64 source, origin = find_template_source(parent, self.template_dirs)63 return context.get_template(parent) 65 64 except TemplateDoesNotExist: 66 65 raise TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent 67 else:68 return get_template_from_string(source, origin, parent)69 66 70 67 def render(self, context): 71 68 compiled_parent = self.get_parent(context) … … 92 89 parent_block.nodelist = block_node.nodelist 93 90 return compiled_parent.render(context) 94 91 95 class ConstantIncludeNode(Node):96 def __init__(self, template_path):97 try:98 t = get_template(template_path)99 self.template = t100 except:101 if settings.TEMPLATE_DEBUG:102 raise103 self.template = None104 105 def render(self, context):106 if self.template:107 return self.template.render(context)108 else:109 return ''110 111 92 class IncludeNode(Node): 112 93 def __init__(self, template_name): 113 94 self.template_name = Variable(template_name) … … 115 96 def render(self, context): 116 97 try: 117 98 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) 120 101 except TemplateSyntaxError, e: 121 102 if settings.TEMPLATE_DEBUG: 122 103 raise … … 178 159 bits = token.contents.split() 179 160 if len(bits) != 2: 180 161 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])184 162 return IncludeNode(bits[1]) 185 163 186 164 register.tag('block', do_block) -
django/utils/text.py
196 196 return str(ustring_re.sub(fix, s)) 197 197 javascript_quote = allow_lazy(javascript_quote, unicode) 198 198 199 smart_split_re = re.compile('("(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'|[^\\s]+)') 200 def smart_split(text): 199 quoted_string_pattern = '"(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'' 200 smart_split_re = re.compile('(%s|[^\\s]+)' % quoted_string_pattern) 201 smart_split_comma_re = re.compile('(%s|[^\\s,]+|,)' % quoted_string_pattern) 202 def smart_split(text, yield_comma=False): 201 203 r""" 202 204 Generator that splits a string by spaces, leaving quoted phrases together. 203 205 Supports both single and double quotes, and supports escaping quotes with … … 212 214 [u'A', u'""funky" style"', u'test.'] 213 215 """ 214 216 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): 216 219 bit = bit.group(0) 217 220 if bit[0] == '"' and bit[-1] == '"': 218 221 yield '"' + bit[1:-1].replace('\\"', '"').replace('\\\\', '\\') + '"'