views:

48

answers:

4

I am writing a template for my first django website.

I am passing a list of dictionaries to the template in a variable. I also need to pass a few other lists which hold boolean flags. (Note: all lists have the same length)

The template looks something like this:

<html>
    <head><title>First page</title></head><body>
        {% for item in data_tables %}
        <table>
        <tbody>
                  <tr><td colspan="15">
                  {% if level_one_flags[forloop.counter-1] %}
                  <tr><td>Premier League
                  {% endif %}
                  <tr><td>Junior league
                  <tr><td>Member count
                  {% if level_two_flags[forloop.counter-1] %}
                  <tr><td>Ashtano League
                  {% endif %}
             </tbody>
        </table>
        {% endfor %}
  </body>
</html>

I am getting the following error:

Template error

In template /mytemplate.html, error at line 7 Could not parse the remainder: '[forloop.counter-1]' from 'level_one_flags[forloop.counter-1]'

I am, not suprised I am getting this error, since I was just trying to see if would work. So far, from the documentation, I have not found out how to obtain the items in a list by index (i.e. other than by enumeration).

Does anyone know how I may access a list by index in a template?

+1  A: 

You use the dot-operator to index the array, or, really, to do anything.

Technically, when the template system encounters a dot, it tries the following lookups, in this order:

* Dictionary lookup
* Attribute lookup
* Method call
* List-index lookup

I don't believe you can do math on the index. You'll have to pass in your array constructed in some other way so that you don't have to do this subtraction.

hughdbrown
Hmm, it does seem a rather silly oversight by the Django developers - given the fact that loop iterations and sequence indices have different bases. I'm sure its me who is doing things the wrong way. Still, at least, thanks to your info, I can access the item - its just that the indexing is wrong. I'll have to find a way of getting the correct zero based indices from the loop structure.
skyeagle
There exists `counter0`. See here: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
Nick Presta
Thanks Nick. I'll remember to use that (counter0) for next time - I knew the django developers wont leave something like that out :).
skyeagle
A: 

Perhaps a better way is to use forloop.last. Of course, this will require that you send to the template the specific level_one_flag and level_two_flag out of the level_one_flags and level_two_flags arrays, but I think this solution keeps a better logical separation between view and template:

<html>
    <head><title>First page</title></head><body>
    {% for item in data_tables %}
    <table>
    <tbody>
              <tr><td colspan="15">
              {% if forloop.last and level_one_flag %}
              <tr><td>Premier League
              {% endif %}
              <tr><td>Junior league
              <tr><td>Member count
              {% if forloop.last and level_two_flag %}
              <tr><td>Ashtano League
              {% endif %}
         </tbody>
    </table>
    {% endfor %}
    </body>
</html>
OmerGertel
A: 

Try using "slice" to access a list by index

http://docs.djangoproject.com/en/dev/ref/templates/builtins/#slice

dannyroa
A: 

In short, Django doesn't do what you want.

The for loop has a number of useful properties within a loop.

forloop.counter     The current iteration of the loop (1-indexed)
forloop.counter0    The current iteration of the loop (0-indexed)
forloop.revcounter  The number of iterations from the end of the loop (1-indexed)
forloop.revcounter0 The number of iterations from the end of the loop (0-indexed)
forloop.first       True if this is the first time through the loop
forloop.last        True if this is the last time through the loop
forloop.parentloop  For nested loops, this is the loop "above" the current one

You could probably use forloop.counter0 to get the zero-based indexes you want; unfortunately, the Django template language doesn't support variable array indexes (You can do {{ foo.5 }}, but you can't do {{ foo.{{bar}} }}).

What I usually do is to try and arrange the data in the view to make it easier to present in the template. As an example, for you could create an array in your view composed of dictionaries so that all you have to do is loop through the array and pull exactly what you need out of the individual dictionaries. For really complicated things, I've gone so far as to create a DataRow object that would correctly format the data for a particular row in a table.

Craig Trader