Malcolm, thanks for continuing this (I was away for a few days). I was thinking about the forloop internals as well, and it seems to me that there's no reason the forloop dictionary needs to be completely new each time around. Why not change forloop to create a new dictionary before the first iteration, then update the dictionary on each iteration rather than replace it?
BTW: this problem also plagues ifchanged: the docs say "check if a value has changed from the last iteration of a loop", which I guess is accurate, but I was surprised to find that it really only works if the ifchanged tag is evaluated on every iteration of the loop. --Ned. Malcolm Tredinnick wrote: > Hey Ned, > > On Sat, 2007-12-29 at 08:27 +1100, Malcolm Tredinnick wrote: > [...] > >> def render(self, context): >> if context[self.varname] == id(context['forloop']): >> return self.nodelist_false.render(context) >> context[self.varname] = id(context['forloop']) >> return self.nodelist_true.render(context) >> > > This guess is rubbish. The problem is that the context['forloop'] > dictionary is a new instance for every iteration of the for-loop, so > there's nothing constant about that outer structure we can use. > > After a bit of sleep, some food and some time spent thinking about this > whilst doing other stuff today, there's a better solution (a.k.a one > that works) attached to this mail. I've even tested this one. > > During any for-loop, the only thing that remains constant is the > "parentloop" dictionary. That dictionary is created anew every time the > *parent* loop steps forwards, but it is referred to by reference for > each iteration of the inner loop. So we can stick a marker into the > parent loop's data structure (even when there's no parent loop, that > data structure is an empty dictionary). > > So, this implementation does depend a bit on the internals of the > ForNode, but that isn't a complete crime. Plus it's been hard to come up > with an alternative. Every time I thought of some tricky data structure > that seemed to do the trick, I was able to break it. A template fragment > such as > > {% for x in data %} > {% if x %} > {% iffirst %} yes {% else %} no {% endfirst %} > {% else %} fail {% endif %} > {% endfor %} > > given data = (0, 1, 1, 0) twice in succession (without recompiling), or > giving data = (0, 1, 1, 0) and data = (0, 0, 1, 0) on successive runs > (again, without recompiling) was enough to break most of my attempts. > > It's also not too hard to extend this to be check whether this is the > first time around the parent loop using a similar method, although > nested "iffirst" tags seems hard. > > Best wishes, > Malcolm > > -- Ned Batchelder, http://nedbatchelder.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---