Django - How to do tuple unpacking in a template 'for' loop

PythonDjangoTemplatesTuplesIterable Unpacking

Python Problem Overview


In my views.py, I'm building a list of two-tuples, where the second item in the tuple is another list, like this:

[ Product_Type_1, [ product_1, product_2 ],
  Product_Type_2, [ product_3, product_4 ]]

In plain old Python, I could iteration the list like this:

for product_type, products in list:
    print product_type
    for product in products:
        print product

I can't seem to do the same thing in my Django template:

{% for product_type, products in product_list %}
    print product_type
    {% for product in products %}
        print product
    {% endfor %}
{% endfor %}

I get this error from Django:

Caught an exception while rendering: zip argument #2 must support iteration

Of course, there is some HTML markup in the template, not print statements. Is tuple unpacking not supported in the Django template language? Or am I going about this the wrong way? All I am trying to do is display a simple hierarchy of objects - there are several product types, each with several products (in models.py, Product has a foreign key to Product_type, a simple one-to-many relationship).

Obviously, I am quite new to Django, so any input would be appreciated.

Python Solutions


Solution 1 - Python

Another way is as follows.

If one has a list of tuples say:

mylst = [(a, b, c), (x, y, z), (l, m, n)]

then one can unpack this list in the template file in the following manner. In my case I had a list of tuples which contained the URL, title, and summary of a document.

{% for item in mylst %}    
     {{ item.0 }} {{ item.1}} {{ item.2 }}    
{% endfor %}

Solution 2 - Python

it would be best if you construct your data like {note the '(' and ')' can be exchanged for '[' and ']' repectively, one being for tuples, one for lists}

[ (Product_Type_1, ( product_1, product_2 )),   (Product_Type_2, ( product_3, product_4 )) ]

and have the template do this:

{% for product_type, products in product_type_list %}
    {{ product_type }}
    {% for product in products %}
        {{ product }}
    {% endfor %}
{% endfor %}

the way tuples/lists are unpacked in for loops is based on the item returned by the list iterator. each iteration only one item was returned. the first time around the loop, Product_Type_1, the second your list of products...

Solution 3 - Python

You must used this way:

{% for product_type, products in product_list.items %}
    {{ product_type }}
    {% for product in products %}
       {{ product }}
    {% endfor %}
{% endfor %}

Don't forget the variable items in the dictionary data

Solution 4 - Python

If you have a fixed number in your tuples, you could just use indexing. I needed to mix a dictionary and the values were tuples, so I did this:

In the view:

my_dict = {'parrot': ('dead', 'stone'), 'lumberjack': ('sleep_all_night', 'work_all_day')}

In the template:

<select>
  {% for key, tuple in my_dict.items %}
    <option value="{{ key }}" important-attr="{{ tuple.0 }}">{{ tuple.1 }}</option>
  {% endfor %}
</select>

Solution 5 - Python

Just send the template a list of product types and do something like:

{% for product_type in product_type_list %}
    {{ product_type }}
    {% for product in product_type.products.all %}
        {{ product }}
    {% endfor %}
{% endfor %}

It's been a little while so I can't remember exactly what the syntax is, let me know if that works. Check the documentation.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChris LawlorView Question on Stackoverflow
Solution 1 - PythonAshwin RaoView Answer on Stackoverflow
Solution 2 - PythonJakeView Answer on Stackoverflow
Solution 3 - PythonYaselView Answer on Stackoverflow
Solution 4 - PythonfamousfilmView Answer on Stackoverflow
Solution 5 - PythonHarley HolcombeView Answer on Stackoverflow