diff -r 6641e941ef1e -r ff1a9aa48cfd app/django/template/defaulttags.py --- a/app/django/template/defaulttags.py Tue Oct 14 12:36:55 2008 +0000 +++ b/app/django/template/defaulttags.py Tue Oct 14 16:00:59 2008 +0000 @@ -39,12 +39,11 @@ class CycleNode(Node): def __init__(self, cyclevars, variable_name=None): - self.cycle_iter = itertools_cycle(cyclevars) + self.cycle_iter = itertools_cycle([Variable(v) for v in cyclevars]) self.variable_name = variable_name def render(self, context): - value = self.cycle_iter.next() - value = Variable(value).resolve(context) + value = self.cycle_iter.next().resolve(context) if self.variable_name: context[self.variable_name] = value return value @@ -158,34 +157,37 @@ return nodelist.render(context) class IfChangedNode(Node): - def __init__(self, nodelist, *varlist): - self.nodelist = nodelist + def __init__(self, nodelist_true, nodelist_false, *varlist): + self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false self._last_seen = None self._varlist = map(Variable, varlist) + self._id = str(id(self)) def render(self, context): - if 'forloop' in context and context['forloop']['first']: + if 'forloop' in context and self._id not in context['forloop']: self._last_seen = None + context['forloop'][self._id] = 1 try: if self._varlist: # Consider multiple parameters. This automatically behaves # like an OR evaluation of the multiple variables. compare_to = [var.resolve(context) for var in self._varlist] else: - compare_to = self.nodelist.render(context) + compare_to = self.nodelist_true.render(context) except VariableDoesNotExist: compare_to = None - if compare_to != self._last_seen: + 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.render(context) + content = self.nodelist_true.render(context) context.pop() return content - else: - return '' + elif self.nodelist_false: + return self.nodelist_false.render(context) + return '' class IfEqualNode(Node): def __init__(self, var1, var2, nodelist_true, nodelist_false, negate): @@ -349,25 +351,40 @@ return self.mapping.get(self.tagtype, '') class URLNode(Node): - def __init__(self, view_name, args, kwargs): + def __init__(self, view_name, args, kwargs, asvar): self.view_name = view_name self.args = args self.kwargs = kwargs + self.asvar = asvar def render(self, context): from django.core.urlresolvers import reverse, NoReverseMatch args = [arg.resolve(context) for arg in self.args] kwargs = dict([(smart_str(k,'ascii'), v.resolve(context)) for k, v in self.kwargs.items()]) + + + # Try to look up the URL twice: once given the view name, and again + # relative to what we guess is the "main" app. If they both fail, + # re-raise the NoReverseMatch unless we're using the + # {% url ... as var %} construct in which cause return nothing. + url = '' try: - return reverse(self.view_name, args=args, kwargs=kwargs) + url = reverse(self.view_name, args=args, kwargs=kwargs) except NoReverseMatch: + project_name = settings.SETTINGS_MODULE.split('.')[0] try: - project_name = settings.SETTINGS_MODULE.split('.')[0] - return reverse(project_name + '.' + self.view_name, - args=args, kwargs=kwargs) + url = reverse(project_name + '.' + self.view_name, + args=args, kwargs=kwargs) except NoReverseMatch: - return '' + if self.asvar is None: + raise + + if self.asvar: + context[self.asvar] = url + return '' + else: + return url class WidthRatioNode(Node): def __init__(self, val_expr, max_expr, max_width): @@ -452,17 +469,17 @@