Ticket #2800: ifchanged-multi-parameters.patch

File ifchanged-multi-parameters.patch, 6.2 KB (added by anonymous, 18 years ago)
  • django/template/defaulttags.py

     
    124124        return nodelist.render(context)
    125125
    126126class IfChangedNode(Node):
    127     def __init__(self, nodelist):
     127    def __init__(self, nodelist, var1=None):
    128128        self.nodelist = nodelist
    129129        self._last_seen = None
     130        self._var1 = var1
    130131
    131132    def render(self, context):
    132133        if context.has_key('forloop') and context['forloop']['first']:
    133134            self._last_seen = None
    134         content = self.nodelist.render(context)
    135         if content != self._last_seen:
     135        try:
     136            if self._var1==None:
     137                compare_to = self.nodelist.render(context)
     138            else:
     139                # Consider multiple parameters.
     140                # This automatically behaves like a OR evaluation of the multiple variables.
     141                compare_to = ",".join([str(resolve_variable(var, context)) for var in self._var1.split(",")])
     142        except VariableDoesNotExist:
     143            compare_to = None       
     144        if  compare_to != self._last_seen:
    136145            firstloop = (self._last_seen == None)
    137             self._last_seen = content
     146            self._last_seen = compare_to
    138147            context.push()
    139148            context['ifchanged'] = {'firstloop': firstloop}
    140149            content = self.nodelist.render(context)
     
    632641    """
    633642    Check if a value has changed from the last iteration of a loop.
    634643
    635     The 'ifchanged' block tag is used within a loop. It checks its own rendered
    636     contents against its previous state and only displays its content if the
    637     value has changed::
     644    The 'ifchanged' block tag is used within a loop. It has two possible uses.
     645    1) It checks its own rendered contents against its previous state and
     646    only displays its content if the value has changed.
     647    2) It checks if (any of) the given variable(s) has changed. ::
    638648
    639649        <h1>Archive for {{ year }}</h1>
    640650
    641651        {% for date in days %}
    642         {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
    643         <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
     652            {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
     653
     654            {% ifchanged date %}date has changed{% endifchanged %}
     655            <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
    644656        {% endfor %}
     657       
     658        <!--
     659          This shall result in printing the date, when it changed and the hour
     660          but when it changed only. The second ifchanged needs to check two variables
     661          the date and the hour in case the current hour to print is the same as
     662          the one from the last day. Here the special case of checking multiple
     663          variables using an ifchnaged is required.
     664        -->
     665        {% for date in days %}
     666            {% ifchanged %} {{date.date}} {% endifchanged %}
     667            {% ifchanged date.hour,date.date %}
     668                {{date.hour}}
     669            {% endifchanged %}
     670        {% endfor %}
    645671    """
    646672    bits = token.contents.split()
    647     if len(bits) != 1:
    648         raise TemplateSyntaxError, "'ifchanged' tag takes no arguments"
     673    if len(bits) > 2:
     674        raise TemplateSyntaxError, "'ifchanged' tag takes either one or none argument"
     675    if len(bits) == 1:
     676        bits.append(None)
    649677    nodelist = parser.parse(('endifchanged',))
    650678    parser.delete_first_token()
    651     return IfChangedNode(nodelist)
     679    return IfChangedNode(nodelist, bits[1])
    652680ifchanged = register.tag(ifchanged)
    653681
    654682#@register.tag
  • tests/regressiontests/templates/tests.py

     
    309309            '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'),
    310310            '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'),
    311311            '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'),
     312            # Test one parameter given to ifchanged.
     313            'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{n}}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),
     314            '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'),
     315            # Test multiple parameters to ifchanged.
     316            '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'),
     317            # 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.
     318            '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'),
     319            # Logically the same as above, just written with explicit ifchanged for the day.
     320            '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'),
    312321
    313322            ### IFEQUAL TAG ###########################################################
    314323            'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),
Back to Top