Supposing a list0
with elements ['a','b','c','d']
, I need to get the nth element depending on a template variable like forloop.counter0
or any other integer available from the template.
So far the better way I found was to create a custom tag as explained here or here and in the django doc.
Once defined you can write something like :
{% for elm in list0 %}
{{ elm }} {{ list1|index:forloop.counter0 }}
{% endfor %}
The example assumes there's another list list1
, with elements ['A','B','C','D']
.
index
is the name of the custom filter, it uses the forloop counter as an index to get each list1
element : list1[0]
, list1[1]
, list1[2]
, list1[3]
So this generates :
a A
b B
c C
d D
But what if you only want to use builtin filters ?
(Or have spare time for recreative stuff ?)
After some research and tests the only way I found is this odd thing :
{% for elm in list0 %}
{% with sl0=forloop.counter0|make_list sl1=forloop.counter|make_list %}
{% with header_id=sl0.0|add:":"|add:sl1.0 %}
{{ elm }} {{ list1|slice:header_id|join:"" }}
{% endwith %}
{% endwith %}
{% endfor %}
what it does :
It uses the slice builtin filter. slice needs a string representing a python list part like
'[2:3]'
which is generated by the secondwith
and the twoadd
. So one need to slice one member at a time using the forloop counters :'[0:1]'
,'[1:2]'
,'[2:3]'
...Butforloop.counter0
andforloop.counter
are integers, andadd
does not generate a string in this case. It tries to get an integer as a result. So it needs to be converted to a string. This is whymake_list
is used in the firstwith
, as it's the only way I found so far to change an integer into a string..finally slice returns a list with one element so it uses ajoin:""
to convert it to a string.
I hope I missed something in the documentation because the code above is.. well.. terrible - but funny.
How could I address this need in an efficient way using django template builtins ?
I agree it should be adressed when building the context in the view and not in the template, but let's say it cannot be done.