1

I'm having a difficult time understanding what Django's forloop.counter is. My intention is to wrap each three iterations of a for loop in a <div>. How I would expect it to work is something like:

{% for staff in staff_members %}
    {% if (forloop.counter + 2 % 3) == 0 %} // if loop is the first of three
    <div class="row">
    {% endif %}
        {{ staff }}

    // close <div class="row"> if loop is last of three
{% endfor %}

This doesn't work because it seems Django doesn't like to operate on the forloop.counter. It seems overly complicated to do this operation in the view, I'd much rather do it in the template as it's purely a presentational / style issue.

0

4 Answers 4

2

This has nothing to do with "Django not liking to operate on the counter". It's simply that Django's template language does not support those sorts of operations, on any variables, by design.

As others have noted, there are tags that can do what you Want. The easiest way is probably with divisibleby:

{% for staff in staff_members %}
    {% if forloop.counter|divisibleby:3 %}
    <div class="row">
    {% endif %}
    {{ staff }}
    {% if forloop.counter0|divisibleby:3 %}
    </div>
{% endfor %}
Sign up to request clarification or add additional context in comments.

1 Comment

I see. I'm much more familiar with the Twig templating language which sometimes blurs the line between view and template sometimes. Appreciate your comment :)
1

You can use cycle tag.

For example:

from django.template import Template, Context
t = Template("""
{% for staff in staff_members %}
     {% cycle '<div class="row">' '' '' as div %}
     {{ staff }}
     {% cycle '' '' '</div>' as div %}
{% endfor %}
{% if not staff_members|length|divisibleby:3 %}
    </div>
{% endif %}
""")
print t.render(Context({'staff_members': [1,2,3,4,5,6,7,8]}))

prints (some empty lines removed to make it easy to read)

<div class="row">
1
2
3
</div>

<div class="row">
4
5
6
</div>

<div class="row">
7
8
</div>

UPDATE Handle closing tag.

Comments

0

forloop.counter gives current iteration of loop and is 1-indexed (that is for first iteration value of forloop.counter is 1)

Comments

0

You will need to use 'divisibleby' along with cycle (as stated by @falsetru) builtins,

For your specific requirement, following will do,

>>> t3 = Template("""
... {% for staff in staff_members %}
...    {% cycle '<div class="row">' '' '' %}
...    {{staff}}
...    {%if forloop.counter|divisibleby:'3' %}
...    </div>
...   {%endif%}
... {%endfor%}
... """)
>>> print t3.render(Context({'staff_members': [1,2,3,4,5,6,7,8,9,10]}))


   <div class="row">
   1

   2

   3

   </div>


   <div class="row">
   4

   5

   6

   </div>


   <div class="row">
   7

   8

   9

   </div>


   <div class="row">
   10

You will need to add extra <\div> in the end if len(staff_members)%3 != 0. I hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.