From 75bc5bc634e90d5ccd2d7fc324df878dc5d4ce5d Mon Sep 17 00:00:00 2001 From: Craig Oldford Date: Mon, 13 Apr 2015 12:27:30 -0300 Subject: [PATCH] Fixed #12199 -- Added the ability to use "as" with the firstof template tag. --- django/template/defaulttags.py | 18 ++++++++++++++---- docs/ref/templates/builtins.txt | 7 +++++++ docs/releases/1.9.txt | 3 +++ .../syntax_tests/test_firstof.py | 7 +++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 6c0bf60094..60d6839ca5 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -110,14 +110,19 @@ class FilterNode(Node): class FirstOfNode(Node): - def __init__(self, variables): + def __init__(self, variables, asvar=None): self.vars = variables + self.asvar = asvar def render(self, context): for var in self.vars: value = var.resolve(context, True) if value: - return render_value_in_context(value, context) + first = render_value_in_context(value, context) + if self.asvar: + context[self.asvar] = first + return '' + return first return '' @@ -748,7 +753,7 @@ def firstof(parser, token): Sample usage:: - {% firstof var1 var2 var3 %} + {% firstof var1 var2 var3 as myvar %} This is equivalent to:: @@ -779,9 +784,14 @@ def firstof(parser, token): """ bits = token.split_contents()[1:] + asvar = None if len(bits) < 1: raise TemplateSyntaxError("'firstof' statement requires at least one argument") - return FirstOfNode([parser.compile_filter(bit) for bit in bits]) + + if len(bits) >= 2 and bits[-2] == 'as': + asvar = bits[-1] + bits = bits[:-2] + return FirstOfNode([parser.compile_filter(bit) for bit in bits], asvar) @register.tag('for') diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index af0da83354..f51e70dcac 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -285,6 +285,13 @@ Or if only some variables should be escaped, you can use:: {% firstof var1 var2|safe var3 "fallback value"|safe %} +You can use the syntax ``{% firstof var1 var2 var3 as value %}`` to store the +output inside a variable. + +.. versionadded:: 1.9 + + The "as" syntax was added. + .. templatetag:: for for diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index d89354ea6a..47c2bc98bc 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -208,6 +208,9 @@ Templates * A warning will now be logged for missing context variables. These messages will be logged to the :ref:`django.template ` logger. +* The :ttag:`firstof` template tag supports storing the output in a variable + using 'as'. + Requests and Responses ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/template_tests/syntax_tests/test_firstof.py b/tests/template_tests/syntax_tests/test_firstof.py index 2c227f2304..a3c8c83151 100644 --- a/tests/template_tests/syntax_tests/test_firstof.py +++ b/tests/template_tests/syntax_tests/test_firstof.py @@ -81,3 +81,10 @@ class FirstOfTagTests(SimpleTestCase): def test_firstof14(self): output = self.engine.render_to_string('firstof14', {'a': '<'}) self.assertEqual(output, '<') + + @setup({'firstof15': '{% firstof a b c as myvar %}'}) + def test_firstof15(self): + ctx = {'a': 0, 'b': 2, 'c': 3} + output = self.engine.render_to_string('firstof15', ctx) + self.assertEqual(ctx['myvar'], '2') + self.assertEqual(output, '')