0

I have two lists:

list1 = ['a','b','c','d']
list2 = [1,2,3,4,5,6,7,8,9,10,11,12]

I want to render them into the template as follows:

a   1  2  3
b   4  5  6
c   7  8  9
d   10 11 12

So the first column with the letters (list1) is row indexes. Each row consists of 3 cells populated from list2.

Template structure is the following:

<div class="row">
   <div class="row-index">row index from list1</div>
   <div class="cell">cell1 from list2</div>
   <div class="cell">cell2 from list2</div>
   <div class="cell">cell3 from list2</div>
</div>

Obviously it is not enough to do a simple nested nested loop here (for list1 and list2):

{% for row_index in list1 %}
   <div class="row">
      <div class="row-index">{{ row_index }}</div>
      {% for cell in list2 %}
      <div class="cell">{{ cell }}</div>
      {% endfor %}
   </div>
{% endfor %}

This will render 4 rows (which is right!) but each row will have 12 cells instead of 3 per row.

Unfortunately, zip_longest(list1, list2) won't help since it adds extra 'None' elements to list1 to make it of equal length with list2. Result is 4 actual row indexes, followed by 8 empty ones. And the cells rendered are all the same for each individual row, e.g. "a 1 1 1", "b 2 2 2", etc.

Is there any way in Django templates to force child loop (inside the nested loop) to do only 3 iterations per 1 iteration of its parent loop?

John Doe
  • 75
  • 1
  • 1
  • 5

2 Answers2

1

Split the longer list into chunks. You can take your pick from the answers to this question, for example:

def chunks(l, n):
    """
    Yield successive n-sized chunks from l.
    code from https://stackoverflow.com/a/312464/113962
    """
    for i in range(0, len(l), n):
        yield l[i:i + n]

Zip the shorter list and the chunked list together.

list1 = ['a','b','c','d']
list2 = [1,2,3,4,5,6,7,8,9,10,11,12]
chunked = chunks(list2, 3)
zipped_lists = zip(list1, chunked)

Then loop through the zipped list in your template, for example:

{% for x, chunk in zipped_list %}
{{ x }} {% for y in chunk %}{{ y }} {% endfor %}
{% endfor %}
Alasdair
  • 298,606
  • 55
  • 578
  • 516
0

Have you looked at the forloop counter?

{% for row_index in list1 %}
   <div class="row">
      <div class="row-index">{{ row_index }}</div>
      {% for cell in list2 %}
           {% if forloop.counter < 4 %}
               <div class="cell">{{ cell }}</div>
           {% endif %}
      {% endfor %}
   </div>
{% endfor %}
Jens Astrup
  • 2,415
  • 2
  • 14
  • 20