Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #4534 -- Added an "else" option to the "ifchanged" template tag.

Patch from SmileyChris.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@8095 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit e29aece743df644cdaa7d8506c6491ac9c1db061 1 parent f763ff4
Malcolm Tredinnick authored July 26, 2008
26  django/template/defaulttags.py
@@ -157,8 +157,8 @@ def render(self, context):
157 157
         return nodelist.render(context)
158 158
 
159 159
 class IfChangedNode(Node):
160  
-    def __init__(self, nodelist, *varlist):
161  
-        self.nodelist = nodelist
  160
+    def __init__(self, nodelist_true, nodelist_false, *varlist):
  161
+        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
162 162
         self._last_seen = None
163 163
         self._varlist = map(Variable, varlist)
164 164
         self._id = str(id(self))
@@ -173,20 +173,21 @@ def render(self, context):
173 173
                 # like an OR evaluation of the multiple variables.
174 174
                 compare_to = [var.resolve(context) for var in self._varlist]
175 175
             else:
176  
-                compare_to = self.nodelist.render(context)
  176
+                compare_to = self.nodelist_true.render(context)
177 177
         except VariableDoesNotExist:
178 178
             compare_to = None
179 179
 
180  
-        if  compare_to != self._last_seen:
  180
+        if compare_to != self._last_seen:
181 181
             firstloop = (self._last_seen == None)
182 182
             self._last_seen = compare_to
183 183
             context.push()
184 184
             context['ifchanged'] = {'firstloop': firstloop}
185  
-            content = self.nodelist.render(context)
  185
+            content = self.nodelist_true.render(context)
186 186
             context.pop()
187 187
             return content
188  
-        else:
189  
-            return ''
  188
+        elif self.nodelist_false:
  189
+            return self.nodelist_false.render(context)
  190
+        return ''
190 191
 
191 192
 class IfEqualNode(Node):
192 193
     def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
@@ -803,9 +804,14 @@ def ifchanged(parser, token):
803 804
             {% endfor %}
804 805
     """
805 806
     bits = token.contents.split()
806  
-    nodelist = parser.parse(('endifchanged',))
807  
-    parser.delete_first_token()
808  
-    return IfChangedNode(nodelist, *bits[1:])
  807
+    nodelist_true = parser.parse(('else', 'endifchanged'))
  808
+    token = parser.next_token()
  809
+    if token.contents == 'else':
  810
+        nodelist_false = parser.parse(('endifchanged',))
  811
+        parser.delete_first_token()
  812
+    else:
  813
+        nodelist_false = NodeList()
  814
+    return IfChangedNode(nodelist_true, nodelist_false, *bits[1:])
809 815
 ifchanged = register.tag(ifchanged)
810 816
 
811 817
 #@register.tag
13  docs/templates.txt
@@ -828,6 +828,19 @@ The 'ifchanged' block tag is used within a loop. It has two possible uses.
828 828
             {% endifchanged %}
829 829
         {% endfor %}
830 830
 
  831
+The ``ifchanged`` tag also takes an optional ``{% else %}`` clause that will
  832
+be displayed if the value has not changed::
  833
+
  834
+    {% for match in matches %}
  835
+        <div style="background-color:
  836
+            {% ifchanged match.ballot_id %}
  837
+                {% cycle red,blue %}
  838
+            {% else %}
  839
+                grey
  840
+            {% endifchanged %}
  841
+        ">{{ match }}</div>
  842
+    {% endfor %}
  843
+
831 844
 ifequal
832 845
 ~~~~~~~
833 846
 
20  tests/regressiontests/templates/tests.py
@@ -565,6 +565,14 @@ def get_template_tests(self):
565 565
             # ifchanged for the day.
566 566
             'ifchanged-param04': ('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),
567 567
 
  568
+            # Test the else clause of ifchanged.
  569
+            'ifchanged-else01': ('{% for id in ids %}{{ id }}{% ifchanged id %}-first{% else %}-other{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-first,1-other,2-first,2-other,2-other,3-first,'),
  570
+
  571
+            'ifchanged-else02': ('{% for id in ids %}{{ id }}-{% ifchanged id %}{% cycle red,blue %}{% else %}grey{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-red,1-grey,2-blue,2-grey,2-grey,3-red,'),
  572
+            'ifchanged-else03': ('{% for id in ids %}{{ id }}{% ifchanged id %}-{% cycle red,blue %}{% else %}{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-red,1,2-blue,2,2,3-red,'),
  573
+
  574
+            'ifchanged-else04': ('{% for id in ids %}{% ifchanged %}***{{ id }}*{% else %}...{% endifchanged %}{{ forloop.counter }}{% endfor %}', {'ids': [1,1,2,2,2,3,4]}, '***1*1...2***2*3...4...5***3*6***4*7'),
  575
+
568 576
             ### IFEQUAL TAG ###########################################################
569 577
             'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),
570 578
             'ifequal02': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 1}, "yes"),
@@ -712,7 +720,7 @@ def get_template_tests(self):
712 720
 
713 721
          	# Inheritance from a template that doesn't have any blocks
714 722
          	'inheritance27': ("{% extends 'inheritance26' %}", {}, 'no tags'),
715  
-         	
  723
+
716 724
             ### I18N ##################################################################
717 725
 
718 726
             # {% spaceless %} tag
@@ -893,16 +901,16 @@ def get_template_tests(self):
893 901
             'cache07': ('{% load cache %}{% cache 2 test foo %}cache07{% endcache %}', {'foo': 1}, 'cache05'),
894 902
 
895 903
             # Allow first argument to be a variable.
896  
-            'cache08': ('{% load cache %}{% cache time test foo %}cache08{% endcache %}', {'foo': 2, 'time': 2}, 'cache06'), 
897  
-            'cache09': ('{% load cache %}{% cache time test foo %}cache09{% endcache %}', {'foo': 3, 'time': -1}, 'cache09'), 
898  
-            'cache10': ('{% load cache %}{% cache time test foo %}cache10{% endcache %}', {'foo': 3, 'time': -1}, 'cache10'), 
  904
+            'cache08': ('{% load cache %}{% cache time test foo %}cache08{% endcache %}', {'foo': 2, 'time': 2}, 'cache06'),
  905
+            'cache09': ('{% load cache %}{% cache time test foo %}cache09{% endcache %}', {'foo': 3, 'time': -1}, 'cache09'),
  906
+            'cache10': ('{% load cache %}{% cache time test foo %}cache10{% endcache %}', {'foo': 3, 'time': -1}, 'cache10'),
899 907
 
900 908
             # Raise exception if we don't have at least 2 args, first one integer.
901 909
             'cache11': ('{% load cache %}{% cache %}{% endcache %}', {}, template.TemplateSyntaxError),
902 910
             'cache12': ('{% load cache %}{% cache 1 %}{% endcache %}', {}, template.TemplateSyntaxError),
903 911
             'cache13': ('{% load cache %}{% cache foo bar %}{% endcache %}', {}, template.TemplateSyntaxError),
904  
-            'cache14': ('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': 'fail'}, template.TemplateSyntaxError), 
905  
-            'cache15': ('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': []}, template.TemplateSyntaxError), 
  912
+            'cache14': ('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': 'fail'}, template.TemplateSyntaxError),
  913
+            'cache15': ('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': []}, template.TemplateSyntaxError),
906 914
 
907 915
             ### AUTOESCAPE TAG ##############################################
908 916
             'autoescape-tag01': ("{% autoescape off %}hello{% endautoescape %}", {}, "hello"),

0 notes on commit e29aece

Please sign in to comment.
Something went wrong with that request. Please try again.