From 9573b663d5327bcb644f6776082c832ec0f49b44 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 21 Dec 2010 00:44:34 +0100 Subject: [PATCH] groupby now supports attributes of attributes. This fixes #10 --- CHANGES | 2 ++ jinja2/compiler.py | 2 +- jinja2/filters.py | 12 +++++++++++- jinja2/testsuite/filters.py | 26 ++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index b171ac2..87f705c 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,8 @@ Version 2.6 allows application developers to disable builtin operators for better security. (For instance limit the mathematical operators to actual integers instead of longs) +- groupby filter now supports dotted notation for grouping by attributes + of attributes. Version 2.5.5 ------------- diff --git a/jinja2/compiler.py b/jinja2/compiler.py index 657a8bc..a4b5a2f 100644 --- a/jinja2/compiler.py +++ b/jinja2/compiler.py @@ -13,7 +13,7 @@ from itertools import chain from copy import deepcopy from jinja2 import nodes from jinja2.nodes import EvalContext -from jinja2.visitor import NodeVisitor, NodeTransformer +from jinja2.visitor import NodeVisitor from jinja2.exceptions import TemplateAssertionError from jinja2.utils import Markup, concat, escape, is_python_keyword, next diff --git a/jinja2/filters.py b/jinja2/filters.py index d1848e4..3a81f70 100644 --- a/jinja2/filters.py +++ b/jinja2/filters.py @@ -595,8 +595,18 @@ def do_groupby(environment, value, attribute): As you can see the item we're grouping by is stored in the `grouper` attribute and the `list` contains all the objects that have this grouper in common. + + .. versionchanged:: 2.6 + It's now possible to use dotted notation to group by the child + attribute of another attribute. """ - expr = lambda x: environment.getitem(x, attribute) + if '.' in attribute: + def expr(item): + for part in attribute.split('.'): + item = environment.getitem(item, part) + return item + else: + expr = lambda x: environment.getitem(x, attribute) return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr))) diff --git a/jinja2/testsuite/filters.py b/jinja2/testsuite/filters.py index b59c9e3..80a6f80 100644 --- a/jinja2/testsuite/filters.py +++ b/jinja2/testsuite/filters.py @@ -252,6 +252,32 @@ class FilterTestCase(JinjaTestCase): "" ] + def test_groupby_multidot(self): + class Date(object): + def __init__(self, day, month, year): + self.day = day + self.month = month + self.year = year + class Article(object): + def __init__(self, title, *date): + self.date = Date(*date) + self.title = title + articles = [ + Article('aha', 1, 1, 1970), + Article('interesting', 2, 1, 1970), + Article('really?', 3, 1, 1970), + Article('totally not', 1, 1, 1971) + ] + tmpl = env.from_string(''' + {%- for year, list in articles|groupby('date.year') -%} + {{ year }}{% for x in list %}[{{ x.title }}]{% endfor %}| + {%- endfor %}''') + assert tmpl.render(articles=articles).split('|') == [ + '1970[aha][interesting][really?]', + '1971[totally not]', + '' + ] + def test_filtertag(self): tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}" "foobar{% endfilter %}") -- 2.26.2