Author: aaugustin Date: 2012-02-14 13:29:50 -0800 (Tue, 14 Feb 2012) New Revision: 17522
Modified: django/trunk/django/template/defaulttags.py django/trunk/tests/regressiontests/templates/tests.py Log: Fixed #17675 -- Changed the implementation of the {% regroup %} template tag to use the context properly when resolving expressions. Modified: django/trunk/django/template/defaulttags.py =================================================================== --- django/trunk/django/template/defaulttags.py 2012-02-14 09:55:09 UTC (rev 17521) +++ django/trunk/django/template/defaulttags.py 2012-02-14 21:29:50 UTC (rev 17522) @@ -10,7 +10,7 @@ TemplateSyntaxError, VariableDoesNotExist, InvalidTemplateLibrary, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END, - get_library, token_kwargs, kwarg_re) + VARIABLE_ATTRIBUTE_SEPARATOR, get_library, token_kwargs, kwarg_re) from django.template.smartif import IfParser, Literal from django.template.defaultfilters import date from django.utils.encoding import smart_str, smart_unicode @@ -287,6 +287,12 @@ self.target, self.expression = target, expression self.var_name = var_name + def resolve_expression(self, obj, context): + # This method is called for each object in self.target. See regroup() + # for the reason why we temporarily put the object in the context. + context[self.var_name] = obj + return self.expression.resolve(context, True) + def render(self, context): obj_list = self.target.resolve(context, True) if obj_list == None: @@ -298,7 +304,7 @@ context[self.var_name] = [ {'grouper': key, 'list': list(val)} for key, val in - groupby(obj_list, lambda v, f=self.expression.resolve: f(v, True)) + groupby(obj_list, lambda obj: self.resolve_expression(obj, context)) ] return '' @@ -1112,10 +1118,16 @@ if lastbits_reversed[1][::-1] != 'as': raise TemplateSyntaxError("next-to-last argument to 'regroup' tag must" " be 'as'") - - expression = parser.compile_filter(lastbits_reversed[2][::-1]) - var_name = lastbits_reversed[0][::-1] + # RegroupNode will take each item in 'target', put it in the context under + # 'var_name', evaluate 'var_name'.'expression' in the current context, and + # group by the resulting value. After all items are processed, it will + # save the final result in the context under 'var_name', thus clearing the + # temporary values. This hack is necessary because the template engine + # doesn't provide a context-aware equivalent of Python's getattr. + expression = parser.compile_filter(var_name + + VARIABLE_ATTRIBUTE_SEPARATOR + + lastbits_reversed[2][::-1]) return RegroupNode(target, expression, var_name) @register.tag Modified: django/trunk/tests/regressiontests/templates/tests.py =================================================================== --- django/trunk/tests/regressiontests/templates/tests.py 2012-02-14 09:55:09 UTC (rev 17521) +++ django/trunk/tests/regressiontests/templates/tests.py 2012-02-14 21:29:50 UTC (rev 17522) @@ -8,7 +8,7 @@ # before importing 'template'. settings.configure() -from datetime import datetime, timedelta +from datetime import date, datetime, timedelta import time import os import sys @@ -1376,6 +1376,33 @@ '{% endfor %},' '{% endfor %}', {}, ''), + + # Regression tests for #17675 + # The date template filter has expects_localtime = True + 'regroup03': ('{% regroup data by at|date:"m" as grouped %}' + '{% for group in grouped %}' + '{{ group.grouper }}:' + '{% for item in group.list %}' + '{{ item.at|date:"d" }}' + '{% endfor %},' + '{% endfor %}', + {'data': [{'at': date(2012, 2, 14)}, + {'at': date(2012, 2, 28)}, + {'at': date(2012, 7, 4)}]}, + '02:1428,07:04,'), + # The join template filter has needs_autoescape = True + 'regroup04': ('{% regroup data by bar|join:"" as grouped %}' + '{% for group in grouped %}' + '{{ group.grouper }}:' + '{% for item in group.list %}' + '{{ item.foo|first }}' + '{% endfor %},' + '{% endfor %}', + {'data': [{'foo': 'x', 'bar': ['ab', 'c']}, + {'foo': 'y', 'bar': ['a', 'bc']}, + {'foo': 'z', 'bar': ['a', 'd']}]}, + 'abc:xy,ad:z,'), + ### SSI TAG ######################################################## # Test normal behavior -- You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-updates@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.