Code

Ticket #6398: add_else_to_for.diff

File add_else_to_for.diff, 3.8 KB (added by jezdez, 6 years ago)

First implementation, including documentation

Line 
1Index: django/template/defaulttags.py
2===================================================================
3--- django/template/defaulttags.py      (revision 7020)
4+++ django/template/defaulttags.py      (working copy)
5@@ -84,10 +84,10 @@
6         return u''
7 
8 class ForNode(Node):
9-    def __init__(self, loopvars, sequence, is_reversed, nodelist_loop):
10+    def __init__(self, loopvars, sequence, is_reversed, nodelist_loop, nodelist_false):
11         self.loopvars, self.sequence = loopvars, sequence
12         self.is_reversed = is_reversed
13-        self.nodelist_loop = nodelist_loop
14+        self.nodelist_loop, self.nodelist_false = nodelist_loop, nodelist_false
15 
16     def __repr__(self):
17         reversed_text = self.is_reversed and ' reversed' or ''
18@@ -98,12 +98,15 @@
19     def __iter__(self):
20         for node in self.nodelist_loop:
21             yield node
22+        for node in self.nodelist_false:
23+            yield node
24 
25     def get_nodes_by_type(self, nodetype):
26         nodes = []
27         if isinstance(self, nodetype):
28             nodes.append(self)
29         nodes.extend(self.nodelist_loop.get_nodes_by_type(nodetype))
30+        nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
31         return nodes
32 
33     def render(self, context):
34@@ -122,6 +125,8 @@
35         if not hasattr(values, '__len__'):
36             values = list(values)
37         len_values = len(values)
38+        if len_values < 1:
39+            return self.nodelist_false.render(context)
40         if self.is_reversed:
41             values = reversed(values)
42         unpack = len(self.loopvars) > 1
43@@ -575,7 +580,7 @@
44 #@register.tag(name="for")
45 def do_for(parser, token):
46     """
47-    Loops over each item in an array.
48+    Loops over each item in an array, with support of ``else``.
49 
50     For example, to display a list of athletes given ``athlete_list``::
51 
52@@ -594,6 +599,17 @@
53             {{ key }}: {{ value }}
54         {% endfor %}
55 
56+    As you can see, the ``for`` tag can take an option ``{% else %}`` clause
57+    that will be displayed if the given array is empty::
58+
59+        <ul>
60+        {% for athlete in athlete_list %}
61+            <li>{{ athlete.name }}</li>
62+        {% else %}
63+            <li>Sorry, no athlete in this list!</li>
64+        {% endfor %}
65+        <ul>
66+
67     The for loop sets a number of variables available within the loop:
68 
69         ==========================  ================================================
70@@ -630,9 +646,14 @@
71                                       " %s" % token.contents)
72 
73     sequence = parser.compile_filter(bits[in_index+1])
74-    nodelist_loop = parser.parse(('endfor',))
75-    parser.delete_first_token()
76-    return ForNode(loopvars, sequence, is_reversed, nodelist_loop)
77+    nodelist_loop = parser.parse(('else', 'endfor',))
78+    token = parser.next_token()
79+    if token.contents == 'else':
80+        nodelist_false = parser.parse(('endfor',))
81+        parser.delete_first_token()
82+    else:
83+        nodelist_false = NodeList()
84+    return ForNode(loopvars, sequence, is_reversed, nodelist_loop, nodelist_false)
85 do_for = register.tag("for", do_for)
86 
87 def do_ifequal(parser, token, negate):
88Index: docs/templates.txt
89===================================================================
90--- docs/templates.txt  (revision 7020)
91+++ docs/templates.txt  (working copy)
92@@ -717,6 +717,18 @@
93         {{ key }}: {{ value }}
94     {% endfor %}
95 
96+**New in Django development version**
97+As you can see, the ``for`` tag can take an optional ``{% else %}`` clause
98+that will be displayed if the given array is empty::
99+
100+    <ul>
101+    {% for athlete in athlete_list %}
102+        <li>{{ athlete.name }}</li>
103+    {% else %}
104+        <li>Sorry, no athlete in this list!</li>
105+    {% endfor %}
106+    <ul>
107+
108 The for loop sets a number of variables available within the loop:
109 
110     ==========================  ================================================