Get list item dynamically in django templates

Solution 1:

This is not possible directly because Django thinks that "x" is the key to lookup in mylist - instead of the value of x. So, when x = 5, Django tries to look up mylist["x"] instead of mylist[5].

Use the following filter as workaround:

@register.filter
def lookup(d, key):
    return d[key]

and use it like

{{ mylist|lookup:x }}

Solution 2:

I notice that @e-satis mentioned it, but I think the built-in slice template tag deserves some love.

{{ item | slice:"2" }} #gets the third element of the list

Solution 3:

Are you sure you can't just do:

{% for item in mylist %}
    {{ item }}
{% endfor %}

With the slice filter, you can even do some customisation.

Solution 4:

The slice tag in Django templates may use python's slicing code, but the syntax is unmistakably different. For instance, if you wanted to get an element of a sequence with a variable, in python you'd write something similar to the following:

>>>mylist = ["0th Element", "1th Element"]
>>>zero, one = 0, 1
>>>mylist[zero]
"0th Element"
>>>mylist[one]
"1th Element"

Using this syntax with the Django slice template tag will return a sliced list in every case, of dubious utility for getting an item of known index:

{% with "0" as zero %}
{% with "1" as one %}
{% with "2" as two %}

{{mylist|slice:zero}} {{mylist|slice:one}} {{mylist|slice:two}}

{% endwith %}
{% endwith %}
{% endwith %}

Renders to the html:

[] ["0th Element"] ["0th Element", "1th Element"]

Note the differences: you are getting the result of mylist[:x] instead of mylist[x].

Django provides enough tools to work around this. The first trick is to use explicit slices like 0:1 for your indices, and then |join:"" the resultant list into a single element. Like so:

{% with "0:1" as zero %}
{{mylist|slice:zero|join:""}}
{% endwith %}

Yields:

0th Element

This comes in particularly handy if you need to access a parent loop's index when dealing with an iterable inside a child loop:

{% for parent in parent_loop %}
    {% cycle "0:1" "1:2" "2:3" as parent_loop_index silent %}
    {% for child in child_loop %}
        {{child|slice:parent_loop_index|join:""}}
    {% endfor %}
{% endfor %}

Completed with nothing but stock parts, although I don't think Django has implemented achievements yet.