[Django]-ForLoop Iterations as List Index in Django Template

3๐Ÿ‘

โœ…

Iโ€™d say that the best approach would be to work on the data in the view before passing it to the template.

For example, the zip builtin can be used to create the rows list based on the lists that contain the columns:

rows = zip(list1, list2, list3, list4)

After that, the template can iterate over the rows one by one and access the columns using index access if needed:

{% for row in rows %}
  {{row.0}} {{row.1}} {{row.2}} {{row.3}}
{% endfor %}
๐Ÿ‘คjcollado

1๐Ÿ‘

You can just create a simple filter to return an item from the list:

@register.filter
def get_item(row, i):
    try:
        return row[i]
    except IndexError:
        return ''

Then:

{{ list1|get_item:num2 }}
๐Ÿ‘คChris Pratt

0๐Ÿ‘

If you would really like to do this in your templates themselves for some reason, you can also write a custom template tag that does it for you:

#app/templatetags/zip.py
from django import template

register = template.Library()

class Zipper(template.Node):
    def __init__(self, format_string, var_name):
        self.format_string = format_string
        self.var_name = var_name
    def render(self, context):
        zippables = [context[tok] for tok in self.format_string.split()]
        import pdb; pdb.set_trace()
        context[self.var_name] = zip(*zippables)
        return ''

import re

@register.tag(name="zip")
def do_zip(parser, token):
    try:
        # Splitting by None == splitting by spaces.
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0])
    m = re.search(r'(.*?) as (\w+)', arg)
    if not m:
        raise template.TemplateSyntaxError("%r tag had invalid arguments" % tag_name)
    format_string, var_name = m.groups()
    return Zipper(format_string, var_name)

Note: this syntax is about to get a lot simpler in Django 1.4, due to the addition of assignment_tag.

Then, just use it like this:

{%load zip%}

{% zip list1 list2 list3 list4 as list_of_rows %}

You can then use list_of_rows wherever you want in that block, including inside two nested for loops.

๐Ÿ‘คNate

Leave a comment