Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #2800: the ifchanged tag now can optionally take paramaters to …

…be checked for changing (instead of always using the content). Thanks, Wolfram Kriesing.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4050 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b1b4e8e7c43bb0ee93646493fcf2df4884c14030 1 parent a14dba5
@jacobian jacobian authored
View
51 django/template/defaulttags.py
@@ -124,17 +124,27 @@ def reverse(data):
return nodelist.render(context)
class IfChangedNode(Node):
- def __init__(self, nodelist):
+ def __init__(self, nodelist, *varlist):
self.nodelist = nodelist
self._last_seen = None
+ self._varlist = varlist
def render(self, context):
if context.has_key('forloop') and context['forloop']['first']:
self._last_seen = None
- content = self.nodelist.render(context)
- if content != self._last_seen:
+ try:
+ if self._varlist:
+ # Consider multiple parameters.
+ # This automatically behaves like a OR evaluation of the multiple variables.
+ compare_to = [resolve_variable(var, context) for var in self._varlist]
+ else:
+ compare_to = self.nodelist.render(context)
+ except VariableDoesNotExist:
+ compare_to = None
+
+ if compare_to != self._last_seen:
firstloop = (self._last_seen == None)
- self._last_seen = content
+ self._last_seen = compare_to
context.push()
context['ifchanged'] = {'firstloop': firstloop}
content = self.nodelist.render(context)
@@ -634,23 +644,34 @@ def ifchanged(parser, token):
"""
Check if a value has changed from the last iteration of a loop.
- The 'ifchanged' block tag is used within a loop. It checks its own rendered
- contents against its previous state and only displays its content if the
- value has changed::
+ The 'ifchanged' block tag is used within a loop. It has two possible uses.
- <h1>Archive for {{ year }}</h1>
+ 1. Checks its own rendered contents against its previous state and only
+ displays the content if it has changed. For example, this displays a list of
+ days, only displaying the month if it changes::
- {% for date in days %}
- {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
- <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
- {% endfor %}
+ <h1>Archive for {{ year }}</h1>
+
+ {% for date in days %}
+ {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
+ <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
+ {% endfor %}
+
+ 2. If given a variable, check if that variable has changed. For example, the
+ following shows the date every time it changes, but only shows the hour if both
+ the hour and the date has changed::
+
+ {% for date in days %}
+ {% ifchanged date.date %} {{date.date}} {% endifchanged %}
+ {% ifchanged date.hour date.date %}
+ {{date.hour}}
+ {% endifchanged %}
+ {% endfor %}
"""
bits = token.contents.split()
- if len(bits) != 1:
- raise TemplateSyntaxError, "'ifchanged' tag takes no arguments"
nodelist = parser.parse(('endifchanged',))
parser.delete_first_token()
- return IfChangedNode(nodelist)
+ return IfChangedNode(nodelist, *bits[1:])
ifchanged = register.tag(ifchanged)
#@register.tag
View
33 docs/templates.txt
@@ -525,16 +525,29 @@ ifchanged
Check if a value has changed from the last iteration of a loop.
-The ``ifchanged`` block tag is used within a loop. It checks its own rendered
-contents against its previous state and only displays its content if the value
-has changed::
-
- <h1>Archive for {{ year }}</h1>
-
- {% for day in days %}
- {% ifchanged %}<h3>{{ day|date:"F" }}</h3>{% endifchanged %}
- <a href="{{ day|date:"M/d"|lower }}/">{{ day|date:"j" }}</a>
- {% endfor %}
+The 'ifchanged' block tag is used within a loop. It has two possible uses.
+
+1. Checks its own rendered contents against its previous state and only
+ displays the content if it has changed. For example, this displays a list of
+ days, only displaying the month if it changes::
+
+ <h1>Archive for {{ year }}</h1>
+
+ {% for date in days %}
+ {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
+ <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
+ {% endfor %}
+
+2. If given a variable, check if that variable has changed. For example, the
+ following shows the date every time it changes, but only shows the hour if both
+ the hour and the date has changed::
+
+ {% for date in days %}
+ {% ifchanged date.date %} {{date.date}} {% endifchanged %}
+ {% ifchanged date.hour date.date %}
+ {{date.hour}}
+ {% endifchanged %}
+ {% endfor %}
ifequal
~~~~~~~
View
15 tests/regressiontests/templates/tests.py
@@ -328,6 +328,21 @@ def test_templates(self):
'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'),
'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'),
'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'),
+
+ # Test one parameter given to ifchanged.
+ 'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),
+ 'ifchanged-param02': ('{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}', { 'num': (1,2,3), 'numx': (5,6,7) }, '..567..567..567'),
+
+ # Test multiple parameters to ifchanged.
+ 'ifchanged-param03': ('{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1,1,2), 'numx': (5,6,6) }, '156156256'),
+
+ # Test a date+hour like construct, where the hour of the last day
+ # is the same but the date had changed, so print the hour anyway.
+ 'ifchanged-param04': ('{% for d in days %}{% ifchanged %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),
+
+ # Logically the same as above, just written with explicit
+ # ifchanged for the day.
+ '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'),
### IFEQUAL TAG ###########################################################
'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),

0 comments on commit b1b4e8e

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