Add "myifchanged" tag, which is different from the standard ifchanged

in two ways:
 * It permits an "else" clause.  This code is from http://code.djangoproject.com/ticket/4534
 * It doesn't push the context while rendering, so context changes can be performed (like the change that cycle makes: putting the current value into the context)

Use this new tag to cycle the row color if the ballot_id has changed, or
if it's a synthetic document.
 - Legacy-Id: 380
This commit is contained in:
Bill Fenner 2007-06-13 18:43:56 +00:00
parent 62b82e5ed1
commit 2bf510f43b
2 changed files with 88 additions and 2 deletions

View file

@ -0,0 +1,85 @@
"""A copy of the IfChanged standard node, updated with
SmileyChris's patch in http://code.djangoproject.com/ticket/4534
and with the context push removed."""
from django.template import Node, NodeList, resolve_variable
from django.template import VariableDoesNotExist
from django.template import Library
from django.conf import settings
import sys
register = Library()
class MyIfChangedNode(Node):
def __init__(self, nodelist_true, nodelist_false, *varlist):
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
self._last_seen = None
self._varlist = varlist
def render(self, context):
if context.has_key('forloop') and context['forloop']['first']:
self._last_seen = None
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_true.render(context)
except VariableDoesNotExist:
compare_to = None
if compare_to != self._last_seen:
firstloop = (self._last_seen == None)
self._last_seen = compare_to
#context.push()
#context['ifchanged'] = {'firstloop': firstloop}
content = self.nodelist_true.render(context)
#context.pop()
return content
else:
if self.nodelist_false:
return self.nodelist_false.render(context)
else:
return ''
#@register.tag
def myifchanged(parser, token):
"""
Check if a value has changed from the last iteration of a loop.
The 'myifchanged' 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 %}
{% myifchanged %}<h3>{{ date|date:"F" }}</h3>{% endmyifchanged %}
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}
2. If given a variable, check whether 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 have changed::
{% for date in days %}
{% myifchanged date.date %} {{ date.date }} {% endmyifchanged %}
{% myifchanged date.hour date.date %}
{{ date.hour }}
{% endmyifchanged %}
{% endfor %}
"""
bits = token.contents.split()
nodelist_true = parser.parse(('else', 'endmyifchanged'))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse(('endmyifchanged',))
parser.delete_first_token()
else:
nodelist_false = NodeList()
return MyIfChangedNode(nodelist_true, nodelist_false, *bits[1:])
myifchanged = register.tag(myifchanged)

View file

@ -1,4 +1,5 @@
<tr bgcolor="#{% if match.primary_flag %}{% cycle F8D6F8,E2AFE2 as ballotcolor %}{% else %}{{ ballotcolor }}{% endif %}">
{% load myifchanged %}
<tr bgcolor="#{% myifchanged match.ballot_id %}{% cycle F8D6F8,E2AFE2 as ballotcolor %}{% else %}{% if match.synthetic %}{% cycle ballotcolor %}{% else %}{{ ballotcolor }}{% endif %}{% endmyifchanged %}">
{% if match.synthetic %}
<td>&nbsp;</td>
{% else %}
@ -30,7 +31,7 @@
{% endif %}
</td>
<td>{{ match.document.revision }}</td>
<td>{% firstof match.job_owner "Not Assigned Yet" %}</td>
<td>{{ match.job_owner }}</td>
<td>{% firstof match.status_date "" %}</td>
<td>{{ match.event_date }}</td>
</tr>