(tl;dr at the bottom)
Let me try to explain what I'm trying to accomplish: I have a two dimensional array, and I would like to display its contents a certain way. I want "rows", and each row can display no more than three "objects", for lack of a better word. So I want to iterate over the array and create my HTML in the process. My idea is this: every "first of three" elements in the array should open up the "row". Every "third of three" elements should close the "row". However, if the last element in the [inner] array does not happen to be the "third of three", it should still close the row. So, for example, if we had something like L=[ [0,1,2,3,4], [5,6,7] ]
, I would want to display it like so:
0 1 2
3 4
5 6 7
Which might be marked up like:
<div>0 1 2</div>
<div>3 4</div>
<div>5 6 7</div>
My first thought was to simply use the modulo operator and see if each iteration was the "first", "second", or "third" of a row, but Django templates don't directly support modulo (more on that later).
So I came up with template code like this:
{% for x in L %}
{% for y in x %}
{% cycle '<div>' '' '' %}
{{ y }}
{% cycle '' '' '</div>' %}
{% endfor %}<br/>
{% endfor %}
And this was a good start. Taking the above example, on 0
we would open a div, on 1
do nothing, on 2
close the div, on 3
open it, and on 4
... well, it wouldn't close, because 4
was not the "third in a series of 3". So, while Django templates don't have modulo, they do have a divisibleby check, so I came up with additional logic to say, if we hit the last element of the [inner] for loop, and it also is not divisible by 3 (so we don't have a duplicate close), then close the div:
{% for x in z %}
{% for y in x %}
{% cycle '<div>' '' '' %}
{{ y }}
{% cycle '' '' '</div>' %}
{% if forloop.last %}
{% if forloop.counter|divisibleby:"3" %}
<!-- Row Already Closed -->
{% else %}
</div>
{% endif %}
{% endif %}
{% endfor %}<br/>
{% endfor %}
This worked better! Now, I got through the whole first inner array with proper markup. My issue is this: apparently, Django's cycle functionality does not reset when you go out of scope of the inner for loop. What this means is, my number 5
from the above example is not opening a div like it should, it is not being recognized as the first in a cycle. In fact, it's actually being recognized as a third, and so it is closing a div!
So I'm not sure where to go from here. This appears to be a known and unfixed issues in Django. Can anyone assist, please?
tl;dr I want to take a 2d array, e.g. L=[ [0,1,2,3,4], [5,6,7] ]
and properly mark it up grouping no more than 3 at a time and without grouping any elements from multiple arrays together, like so:
0 1 2
3 4
5 6 7
What would be the template code for that and why?
You should be able to use {% if forloop.counter0|divisibleby:"3" %}
to determine when to open the <div>
tag, and {% if forloop.last or forloop.counter|divisibleby:"3" %}
to determine when to close the </div>
tag.
{% for x in z %}
{% for y in x %}
{% if forloop.counter0|divisibleby:"3" %}<div>{% endif %}
{{ y }}
{% if forloop.last or forloop.counter|divisibleby:"3" %}</div>{% endif %}
{% endfor %}<br/>
{% endfor %}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With