diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index ed11f2c1ae..cf72d8f26e 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -354,6 +354,23 @@ class WidthRatioNode(Node): return '' return str(int(round(ratio))) +class WithNode(Node): + def __init__(self, var, name, nodelist): + self.var = var + self.name = name + self.nodelist = nodelist + + def __repr__(self): + return "" + + def render(self, context): + val = self.var.resolve(context) + context.push() + context[self.name] = val + output = self.nodelist.render(context) + context.pop() + return output + #@register.tag def comment(parser, token): """ @@ -967,3 +984,23 @@ def widthratio(parser, token): return WidthRatioNode(parser.compile_filter(this_value_expr), parser.compile_filter(max_value_expr), max_width) widthratio = register.tag(widthratio) + +#@register.tag +def do_with(parser, token): + """ + Add a value to the context (inside of this block) for caching and easy + access. For example:: + + {% with person.some_sql_method as total %} + {{ total }} object{{ total|pluralize }} + {% endwith %} + """ + bits = list(token.split_contents()) + if len(bits) != 4 or bits[2] != "as": + raise TemplateSyntaxError, "%r expected format is 'value as name'" % tagname + var = parser.compile_filter(bits[1]) + name = bits[3] + nodelist = parser.parse(('endwith',)) + parser.delete_first_token() + return WithNode(var, name, nodelist) +do_with = register.tag('with', do_with) diff --git a/docs/templates.txt b/docs/templates.txt index db748ae432..37fd1cdea4 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -872,6 +872,22 @@ Above, if ``this_value`` is 175 and ``max_value`` is 200, the the image in the above example will be 88 pixels wide (because 175/200 = .875; .875 * 100 = 87.5 which is rounded up to 88). +with +~~~~ + +**New in Django development version** + +Useful for caching a method which will be used more than once. + +For example:: + + {% with person.some_sql_method as total %} + {{ total }} person object{{ total|pluralize }} + {% endwith %} + +The populated variable (in the example above, ``total``) is only available +inside of ``{% with %}`` block. + Built-in filter reference ------------------------- diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 375fd36196..967767ee50 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -650,6 +650,10 @@ class Templates(unittest.TestCase): 'widthratio09': ('{% widthratio a b %}', {'a':50,'b':100}, template.TemplateSyntaxError), 'widthratio10': ('{% widthratio a b 100.0 %}', {'a':50,'b':100}, template.TemplateSyntaxError), + ### WITH TAG ######################################################## + 'with01': ('{% with dict.key as key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, '50'), + 'with02': ('{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}', {'dict': {'key':50}}, ('50-50-50', 'INVALID50-50-50INVALID')), + ### NOW TAG ######################################################## # Simple case 'now01' : ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),