[svn] added groupby filter and fixed some small bugs
--HG--
branch : trunk
diff --git a/jinja/filters.py b/jinja/filters.py
index 619148b..3f621a7 100644
--- a/jinja/filters.py
+++ b/jinja/filters.py
@@ -11,7 +11,7 @@
import re
from random import choice
from urllib import urlencode, quote
-from jinja.utils import urlize, escape, reversed, sorted
+from jinja.utils import urlize, escape, reversed, sorted, groupby
from jinja.datastructure import TemplateData
from jinja.exceptions import FilterArgumentError
@@ -849,6 +849,39 @@
return wrapped
+def do_groupby(attribute):
+ """
+ Group a sequence of objects by a common attribute.
+
+ If you for example have a list of dicts or objects that represent persons
+ with `gender`, `first_name` and `last_name` attributes and you want to
+ group all users by genders you can do something like the following
+ snippet:
+
+ .. sourcecode:: html+jinja
+
+ <ul>
+ {% for group in persons|groupby('gender') %}
+ <li>{{ group.grouper }}<ul>
+ {% for person in group.list %}
+ <li>{{ person.first_name }} {{ person.last_name }}</li>
+ {% endfor %}</ul></li>
+ {% endfor %}
+ </ul>
+
+ 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.
+ """
+ def wrapped(env, context, value):
+ expr = lambda x: env.get_attribute(x, attribute)
+ return [{
+ 'grouper': a,
+ 'list': list(b)
+ } for a, b in groupby(sorted(value, key=expr), expr)]
+ return wrapped
+
+
FILTERS = {
'replace': do_replace,
'upper': do_upper,
@@ -895,5 +928,6 @@
'sum': do_sum,
'abs': do_abs,
'round': do_round,
- 'sort': do_sort
+ 'sort': do_sort,
+ 'groupby': do_groupby
}