ford ford - 3 months ago 18
Python Question

Stable sorting in Jinja2

It is possible to apply the sort filter in Jinja2 successively to sort a list first by one attribute, then by another? This seems like a natural thing to do, but in my testing, the preceeding sort is completely unstable and all sorting is lost.

I already worked around it by sorting first in python before passing the list to the template, but I would like to know if it's possible to sort "stable" in Jinja2.

The way I applied the filter was like so:

{{ item_list|sort(attribute='value')|sort(attribute='color') }}


What I had hoped to see was the list sorted by
color
, with the elements sharing a color sorted by
value
. Instead, it looked the same as if the
value
sort never happened.

For example, from this list:

2 red
3 blue
3 red
2 blue
1 blue
4 red


I would like something like this:

1 blue
2 blue
3 blue
2 red
3 red
4 red


I looked at the groupby filter but that implementation seems too complicated (would require nested for loops).

Answer

I am not aware of a native jinja2 filter that can do this. To sort a list based on multiple attributes,you can define a custom filter in jinja2.

From the accepted answer to this question, you can write your own filter

import operator

def sort_multi(L,*operators): 
    L.sort(key=operator.itemgetter(*operators))
    return L

Register it in your application environment. So for pyramid, you would do something like

env = config.get_jinja2_environment()
env.filters['sort_multi'] = sort_multi

And finally in your templates

{{item_list|sort_multi('value','color')}}
Comments