Author: aaugustin
Date: 2011-12-09 14:13:27 -0800 (Fri, 09 Dec 2011)
New Revision: 17187

Modified:
   django/trunk/django/template/defaulttags.py
   django/trunk/docs/ref/templates/builtins.txt
   django/trunk/docs/releases/1.4.txt
   django/trunk/tests/regressiontests/templates/tests.py
Log:
Fixed #17348 -- Implemented {% elif %}. Refs #3100.


Modified: django/trunk/django/template/defaulttags.py
===================================================================
--- django/trunk/django/template/defaulttags.py 2011-12-09 22:10:52 UTC (rev 
17186)
+++ django/trunk/django/template/defaulttags.py 2011-12-09 22:13:27 UTC (rev 
17187)
@@ -250,32 +250,38 @@
         return self.nodelist_false.render(context)
 
 class IfNode(Node):
-    child_nodelists = ('nodelist_true', 'nodelist_false')
 
-    def __init__(self, var, nodelist_true, nodelist_false=None):
-        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
-        self.var = var
+    def __init__(self, conditions_nodelists):
+        self.conditions_nodelists = conditions_nodelists
 
     def __repr__(self):
-        return "<If node>"
+        return "<IfNode>"
 
     def __iter__(self):
-        for node in self.nodelist_true:
-            yield node
-        for node in self.nodelist_false:
-            yield node
+        for _, nodelist in self.conditions_nodelists:
+            for node in nodelist:
+                yield node
 
+    @property
+    def nodelist(self):
+        return NodeList(node for _, nodelist in self.conditions_nodelists for 
node in nodelist)
+
     def render(self, context):
-        try:
-            var = self.var.eval(context)
-        except VariableDoesNotExist:
-            var = None
+        for condition, nodelist in self.conditions_nodelists:
 
-        if var:
-            return self.nodelist_true.render(context)
-        else:
-            return self.nodelist_false.render(context)
+            if condition is not None:           # if / elif clause
+                try:
+                    match = condition.eval(context)
+                except VariableDoesNotExist:
+                    match = None
+            else:                               # else clause
+                match = True
 
+            if match:
+                return nodelist.render(context)
+
+        return ''
+
 class RegroupNode(Node):
     def __init__(self, target, expression, var_name):
         self.target, self.expression = target, expression
@@ -825,6 +831,8 @@
 
         {% if athlete_list %}
             Number of athletes: {{ athlete_list|count }}
+        {% elif athlete_in_locker_room_list %}
+            Athletes should be out of the locker room soon!
         {% else %}
             No athletes.
         {% endif %}
@@ -832,8 +840,9 @@
     In the above, if ``athlete_list`` is not empty, the number of athletes will
     be displayed by the ``{{ athlete_list|count }}`` variable.
 
-    As you can see, the ``if`` tag can take an option ``{% else %}`` clause
-    that will be displayed if the test fails.
+    As you can see, the ``if`` tag may take one or several `` {% elif %}``
+    clauses, as well as an ``{% else %}`` clause that will be displayed if all
+    previous conditions fail. These clauses are optional.
 
     ``if`` tags may use ``or``, ``and`` or ``not`` to test a number of
     variables or to negate a given variable::
@@ -871,17 +880,33 @@
 
     Operator precedence follows Python.
     """
+    # {% if ... %}
     bits = token.split_contents()[1:]
-    var = TemplateIfParser(parser, bits).parse()
-    nodelist_true = parser.parse(('else', 'endif'))
+    condition = TemplateIfParser(parser, bits).parse()
+    nodelist = parser.parse(('elif', 'else', 'endif'))
+    conditions_nodelists = [(condition, nodelist)]
     token = parser.next_token()
+
+    # {% elif ... %} (repeatable)
+    while token.contents.startswith('elif'):
+        bits = token.split_contents()[1:]
+        condition = TemplateIfParser(parser, bits).parse()
+        nodelist = parser.parse(('elif', 'else', 'endif'))
+        conditions_nodelists.append((condition, nodelist))
+        token = parser.next_token()
+
+    # {% else %} (optional)
     if token.contents == 'else':
-        nodelist_false = parser.parse(('endif',))
-        parser.delete_first_token()
-    else:
-        nodelist_false = NodeList()
-    return IfNode(var, nodelist_true, nodelist_false)
+        nodelist = parser.parse(('endif',))
+        conditions_nodelists.append((None, nodelist))
+        token = parser.next_token()
 
+    # {% endif %}
+    assert token.contents == 'endif'
+
+    return IfNode(conditions_nodelists)
+
+
 @register.tag
 def ifchanged(parser, token):
     """

Modified: django/trunk/docs/ref/templates/builtins.txt
===================================================================
--- django/trunk/docs/ref/templates/builtins.txt        2011-12-09 22:10:52 UTC 
(rev 17186)
+++ django/trunk/docs/ref/templates/builtins.txt        2011-12-09 22:13:27 UTC 
(rev 17187)
@@ -366,6 +366,8 @@
 
     {% if athlete_list %}
         Number of athletes: {{ athlete_list|length }}
+    {% elif athlete_in_locker_room_list %}
+        Athletes should be out of the locker room soon!
     {% else %}
         No athletes.
     {% endif %}
@@ -373,9 +375,14 @@
 In the above, if ``athlete_list`` is not empty, the number of athletes will be
 displayed by the ``{{ athlete_list|length }}`` variable.
 
-As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that
-will be displayed if the test fails.
+As you can see, the ``if`` tag may take one or several `` {% elif %}``
+clauses, as well as an ``{% else %}`` clause that will be displayed if all
+previous conditions fail. These clauses are optional.
 
+.. versionadded:: 1.4
+
+The ``if`` tag now supports ``{% elif %}`` clauses.
+
 Boolean operators
 ^^^^^^^^^^^^^^^^^
 

Modified: django/trunk/docs/releases/1.4.txt
===================================================================
--- django/trunk/docs/releases/1.4.txt  2011-12-09 22:10:52 UTC (rev 17186)
+++ django/trunk/docs/releases/1.4.txt  2011-12-09 22:13:27 UTC (rev 17187)
@@ -484,6 +484,8 @@
   be able to retrieve a translation string without displaying it but setting
   a template context variable instead.
 
+* The :ttag:`if` template tag now supports ``{% elif %}`` clauses.
+
 * A new plain text version of the HTTP 500 status code internal error page
   served when :setting:`DEBUG` is ``True`` is now sent to the client when
   Django detects that the request has originated in JavaScript code

Modified: django/trunk/tests/regressiontests/templates/tests.py
===================================================================
--- django/trunk/tests/regressiontests/templates/tests.py       2011-12-09 
22:10:52 UTC (rev 17186)
+++ django/trunk/tests/regressiontests/templates/tests.py       2011-12-09 
22:13:27 UTC (rev 17187)
@@ -394,7 +394,7 @@
         try:
             t = Template("{% if 1 %}lala{% endblock %}{% endif %}")
         except TemplateSyntaxError, e:
-            self.assertEqual(e.args[0], "Invalid block tag: 'endblock', 
expected 'else' or 'endif'")
+            self.assertEqual(e.args[0], "Invalid block tag: 'endblock', 
expected 'elif', 'else' or 'endif'")
 
     def test_templates(self):
         template_tests = self.get_template_tests()
@@ -823,6 +823,17 @@
             'if-tag02': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": 
False}, "no"),
             'if-tag03': ("{% if foo %}yes{% else %}no{% endif %}", {}, "no"),
 
+            'if-tag04': ("{% if foo %}foo{% elif bar %}bar{% endif %}", 
{'foo': True}, "foo"),
+            'if-tag05': ("{% if foo %}foo{% elif bar %}bar{% endif %}", 
{'bar': True}, "bar"),
+            'if-tag06': ("{% if foo %}foo{% elif bar %}bar{% endif %}", {}, 
""),
+            'if-tag07': ("{% if foo %}foo{% elif bar %}bar{% else %}nothing{% 
endif %}", {'foo': True}, "foo"),
+            'if-tag08': ("{% if foo %}foo{% elif bar %}bar{% else %}nothing{% 
endif %}", {'bar': True}, "bar"),
+            'if-tag09': ("{% if foo %}foo{% elif bar %}bar{% else %}nothing{% 
endif %}", {}, "nothing"),
+            'if-tag10': ("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% 
else %}nothing{% endif %}", {'foo': True}, "foo"),
+            'if-tag11': ("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% 
else %}nothing{% endif %}", {'bar': True}, "bar"),
+            'if-tag12': ("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% 
else %}nothing{% endif %}", {'baz': True}, "baz"),
+            'if-tag13': ("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% 
else %}nothing{% endif %}", {}, "nothing"),
+
             # Filters
             'if-tag-filter01': ("{% if foo|length == 5 %}yes{% else %}no{% 
endif %}", {'foo': 'abcde'}, "yes"),
             'if-tag-filter02': ("{% if foo|upper == 'ABC' %}yes{% else %}no{% 
endif %}", {}, "no"),

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to