Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access list using variable indexes in Django templates?

Say, I have two lists of objects, foo and bar. In a Django template, while looping through foo, there's a counter that keeps track of the current index/iteration and the counter is used to access bar. The problem here is I don't think Django template system supports accessing list using variable indexes. Is that true? If so, is there any workaround for the problem (other than repeating the same piece of html/template code with hard-coded indexes)?

Code demonstration:

{% for x in foo %}
  <span>{{ x.name }} vs. {{ bar.{{ forloop.counter0 }}.name }}</span>
{% endfor %}

Django template doesn't like {{ bar.{{ forloop.counter0 }}.name }}

Note: I am using Django 1.4

like image 766
tamakisquare Avatar asked Dec 07 '12 21:12

tamakisquare


2 Answers

You are correct that Django templates do not directly allow this, and it's because Django tries to force you to put pretty much all your presentation logic in your views. Your best option is to make a list of dicts in your context in your view, so you can iterate of that and access the members by name. Or:

  • zip your lists together instead of making them a dict and access them using {% for fooItem, barItem in zippedList %}.
  • use a less limiting templating language, like Jinja2
  • use a custom template filter, as suggested by Yuji Tomita
like image 184
acjay Avatar answered Oct 15 '22 10:10

acjay


Right, you can't resolve variable names. Definitely try very hard to put this logic in the view.

But 5% of the time, I do find this extremely limiting at times requiring too much logic in the view / changes required outside the template authors control. I've come to accept a few personal customizations, allowing for variable assignment within the view as well as simple variable resolution.

It's quite simple to build a template tag that does so though, using the template engines "all lookups in one" system (index, attribute, key).

from django.template import Variable, VariableDoesNotExist

@register.assignment_tag()
def resolve(lookup, target):
    try:
        return Variable(lookup).resolve(target)
    except VariableDoesNotExist:
        return None

{% resolve some_list some_index as value %}
{% resolve some_dict some_dict_key as value %}
like image 42
Yuji 'Tomita' Tomita Avatar answered Oct 15 '22 11:10

Yuji 'Tomita' Tomita