Django's dictsort template tag

Sat 26 October 2013

dictsort [1]
Takes a list of dictionaries and returns that list sorted by the key given in the argument. Eg: {{ value|dictsort:"name" }}

The documentation would let you to believe you can only sort dicts with it. What to do if you have a list of strings ? After a bit of fumbling around it turns out that dictsort doesn't do a mere __getitem__ on each object but instead will take each object as a template context and evaluate the key as a variable, like {{ name }} would.

What does this mean ? It means you can sort a list of strings by using the least changing method as the sort attribute. Remember that Django automatically calls any functions in templates. Example:

>>> from django.template import Template, Context
>>> print Template("""{% for i in items|dictsort:"lstrip" %}
...     {{ i }}
... {% endfor %}""").render(Context({
...     'items': ["x", "a", "c", "b"]
... }))

Of-course, this won't work very well if your strings start with spaces.

What else can you do? You can get in depth:

>>> print Template("""{% for i in items|dictsort:"a.b.c.d" %}
...     {{ i|safe }}
... {% endfor %}""").render(Context({
...     'items': [
...         {'a': {'b': {'c': {'d': "x"}}}},
...         {'a': {'b': {'c': {'d': "a"}}}},
...         {'a': {'b': {'c': {'d': "c"}}}},
...         {'a': {'b': {'c': {'d': "b"}}}},
...     ]
... }))
    {'a': {'b': {'c': {'d': 'a'}}}}
    {'a': {'b': {'c': {'d': 'b'}}}}
    {'a': {'b': {'c': {'d': 'c'}}}}
    {'a': {'b': {'c': {'d': 'x'}}}}

Wanted to sort by something in lowercase ? Yep, you can do that too and you should always use lower as the last part in the key for strings. No one wants see stuff sorted by case:

>>> print Template("""{% for i in items|dictsort:"key.lower" %}
...     {{ i.key }}
... {% endfor %}""").render(Context({
...     'items': [
...         {'key': "X"},
...         {'key': "a"},
...         {'key': "c"},
...         {'key': "B"},
...     ]
... }))

This entry was tagged as python django

blog comments powered by Disqus