Django template {%for%} tag add li every 4th element

I need to represent collection in the template and wrap every four elements in the

<li></li>

The template should be like this:

<ul>
    <li>
         <a></a>
         <a></a>
         <a></a>
         <a></a>
    </li>
    <li>
         <a></a>
         <a></a>
         <a></a>
         <a></a>
    </li>
    <li>
         <a></a>
         <a></a>
         <a></a>
         <a></a>
    </li>
</ul>

So i need to do it in the {% for %}

{% for obj in objects %}
 {#add at 1th and every 4th element li wrap somehow#}
    <a>{{object}}</a>
 {# the same closing tag li#}
{% endfor %}

Answers


The following should solve your problem, using built-in template tags :

<ul>
    <li>
    {% for obj in objects %}
        <a>{{ obj }}</a>

    {# if the the forloop counter is divisible by 4, close the <li> tag and open a new one #}
    {% if forloop.counter|divisibleby:4 %}
    </li>
    <li>
    {% endif %}

    {% endfor %}
    </li>
</ul>

You can use the divisibleby tag as mentioned before, but for template clearing purposes I usually prefer a helper function that returns a generator:

def grouped(l, n):
    for i in xrange(0, len(l), n):
        yield l[i:i+n]

example simplistic view:

from app.helpers import grouped

def foo(request):
    context['object_list'] = grouped(Bar.objects.all(), 4)
    return render_to_response('index.html', context)

example template:

{% for group in object_list %}
   <ul>
        {% for object in group %}
            <li>{{ object }}</li>
        {% endfor %}
   </ul>
{% endfor %}

you can use divisibleby built-in filter, here is link to django documentation

so something like this would work

{% if value|divisibleby 4 %}
#your conditional code
{% endif %}

I personally would consider to separate the elements in the view before passing them to the template and then using nested for loops. Except this you really only have the filter or templatetag option as Vaibhav Mishra mentioned.


if you want to work it with checking first forloop and last forloop you could use this :

<ul>
{% for obj in objects %}
{% if forloop.first %}
    <li>
{% endif %}
        <a>{{obj}}</a>
{% if forloop.counter|divisibleby:4 and not forloop.first %}
    </li>
    <li>
{% endif %}
{% if forloop.last %}
    </li>
{% endif %}
{% endfor %}
</ul>

Need Your Help

Ruby on Rails plural (controller) and singular (model) convention - explanation

ruby-on-rails ruby activerecord

As per Ruby on Rails convention, controller names get pluralized while model names are singular. Example : a Users controller, but a User model.