Introduction
So I ran into an interesting situation this weekend where I needed to use a variable as a dictionary key in a Django template. I had a dictionary and I wanted to iterate through it in order by key. Since the dictionary is an unordered data structure I created a list of the keys, sorted them, then iterated through the list using the iterator as the key for the dictionary.
d={"a":"apple", "b":"banana", "m":"mango", "e":"egg", "c":"carrot"}
ls = sorted(d)
print ls
for i in ls:
print d[i]
Output:
['a','b','c','e','m']
'apple'
'banana'
'carrot'
'egg'
'mango'
Problem
This works great in python, but in django templates you can't use variables as a key for a dictionary. Here is an example of code in a template that DOESN'T WORK.
{% for i in ls %}
{{ d.i }}
{% endfor %}
Solution
My solution was to come up with a custom template filter that allowed me to use the variable as a dictionary key. To create a template filter you first need to create a folder in your app called templatetags (don't forget the init.py). Then create a file where you will put your code. The name doesn't really matter but it will affect how we will import the template filter later so keep that in mind. I like the conventions
project/
app/
templatetags/
__init__.py
dictionary_extras.py
Next we need to write our template filter and register it to the template library. First we import the template module and create an instance of a template library so we can register our template filter.
from django import template
register = template.Library()
We then use a handy decorator to register our filter. If you use the name argument, you can give your filter a specific name, otherwise it will use the function name by default
@register.filter(name='access')
def access(value, arg):
return value[arg]
There we go, we're all done. We can now use the access filter on a dictionary in templates as long as we load dictionary_extras. A full example below.
Example
dictionary_extras.py:
from django import template
register = template.Library()
@register.filter(name='access')
def access(value, arg):
return value[arg]
views.py:
...
context["d"] = {"a":"apple", "b":"banana", "m":"mango", "e":"egg", "c":"carrot"}
context["ls"] = sorted(d)
return context
test.html:
{% load dictionary_extras %}
{% for key in ls %}
{{ d|access:key }}
{% endfor %}