Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

groupby now supports attributes of attributes. This fixes #10

  • Loading branch information...
commit 9573b663d5327bcb644f6776082c832ec0f49b44 1 parent 9adf937
@mitsuhiko authored
View
2  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
-------------
View
2  jinja2/compiler.py
@@ -13,7 +13,7 @@
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
View
12 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)))
View
26 jinja2/testsuite/filters.py
@@ -252,6 +252,32 @@ def test_groupby(self):
""
]
+ 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 %}")
Please sign in to comment.
Something went wrong with that request. Please try again.