sort now also accepts an attribute
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 24 Jan 2011 00:05:47 +0000 (01:05 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 24 Jan 2011 00:05:47 +0000 (01:05 +0100)
CHANGES
jinja2/filters.py
jinja2/testsuite/filters.py

diff --git a/CHANGES b/CHANGES
index a410c9ed612c9899055e4903203d2da1ee79db12..7cda7b22a7b879424860403c7b5864e7c4568e8a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -28,6 +28,7 @@ Version 2.6
   incompatible change.  The argument to the filter previously was the
   optional starting index which defaultes to zero.  This now became the
   second argument to the function because it's rarely used.
+- like sum, sort now also makes it possible to order items by attribute.
 
 Version 2.5.5
 -------------
index 82f0153da773287b1edf9941df3862b5001e38d1..a51d25b5ca998596bbb92c4da9218f66de18169a 100644 (file)
@@ -191,7 +191,9 @@ def do_dictsort(value, case_sensitive=False, by='key'):
     return sorted(value.items(), key=sort_func)
 
 
-def do_sort(value, reverse=False, case_sensitive=False):
+@environmentfilter
+def do_sort(environment, value, reverse=False, case_sensitive=False,
+            attribute=None):
     """Sort an iterable.  Per default it sorts ascending, if you pass it
     true as first argument it will reverse the sorting.
 
@@ -204,6 +206,18 @@ def do_sort(value, reverse=False, case_sensitive=False):
         {% for item in iterable|sort %}
             ...
         {% endfor %}
+
+    It is also possible to sort by an attribute (for example to sort
+    by the date of an object) by specifying the `attribute` parameter:
+
+    .. sourcecode:: jinja
+
+        {% for item in iterable|sort(attribute='date') %}
+            ...
+        {% endfor %}
+
+    .. versionchanged:: 2.6
+       The `attribute` parameter was added.
     """
     if not case_sensitive:
         def sort_func(item):
@@ -212,6 +226,10 @@ def do_sort(value, reverse=False, case_sensitive=False):
             return item
     else:
         sort_func = None
+    if attribute is not None:
+        getter = make_attrgetter(environment, attribute)
+        def sort_func(item, processor=sort_func or (lambda x: x)):
+            return processor(getter(item))
     return sorted(value, key=sort_func, reverse=reverse)
 
 
index 6331d76e424dd8c5600c6b62c2fbaa619af700f7..64cd0a902ad92696388e4cecfa858ba37994d9d1 100644 (file)
@@ -257,6 +257,15 @@ class FilterTestCase(JinjaTestCase):
         tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
         assert tmpl.render() == "['Bar', 'blah', 'foo']"
 
+    def test_sort4(self):
+        class Magic(object):
+            def __init__(self, value):
+                self.value = value
+            def __unicode__(self):
+                return unicode(self.value)
+        tmpl = env.from_string('''{{ items|sort(attribute='value')|join }}''')
+        assert tmpl.render(items=map(Magic, [3, 2, 4, 1])) == '1234'
+
     def test_groupby(self):
         tmpl = env.from_string('''
         {%- for grouper, list in [{'foo': 1, 'bar': 2},