128
votes

I'm looking for a way to use something like the modulus operator in django. What I am trying to do is to add a classname to every fourth element in a loop.

With modulus it would look like this:

{% for p in posts %}
    <div class="post width1 height2 column {% if forloop.counter0 % 4 == 0 %}first{% endif %}}">
        <div class="preview">

        </div>
        <div class="overlay">

        </div>
        <h2>p.title</h2>
    </div>
{% endfor %}

Of course this doesn't work because % is a reserved character. Is there any other way to do this?

4
Did you even try it? Django provides the templatetag tag, but that covers {%, %}, etc. (not %). - Platinum Azure
yes, I tried it, but I get the following error: Could not parse the remainder: '%' from '%' I assume it is because it doesn't know how to pare the modulor. The operator is also not listed on the docs docs.djangoproject.com/en/dev/ref/templates/builtins/… - underdoeg

4 Answers

228
votes

You need divisibleby, a built-in django filter.

{% for p in posts %}
    <div class="post width1 height2 column {% if forloop.counter0|divisibleby:4 %}first{% endif %}">
        <div class="preview">

        </div>
        <div class="overlay">

        </div>
        <h2>p.title</h2>
    </div>
{% endfor %}
16
votes

You can't use the modulus operator in Django template tags, but it would be easy enough to write a filter to do so. Something like this should work:

@register.filter
def modulo(num, val):
    return num % val

And then:

{% ifequal forloop.counter0|modulo:4 0 %}

You could even do something like this, instead:

@register.filter
def modulo(num, val):
    return num % val == 0

And then:

{% if forloop.counter0|modulo:4 %}

Or you could use the cycle tag:

<div class="post width1 height2 column {% cycle 'first' '' '' '' %}">
15
votes

Bootstrap rows and columns example. New row every 4 items. Also close last row even if there are less than 4 items.

myapp/templatetags/my_tags.py

from django import template

register = template.Library()

@register.filter
def modulo(num, val):
    return num % val

html template

{% load my_tags %}

{% for item in all_items %} 
    {% if forloop.counter|modulo:4 == 1 %}
        <div class="row">
    {% endif %}

        <div class="col-sm-3">
            {{ item }}
        </div>

    {% if forloop.last or forloop.counter|modulo:4 == 0 %}
        </div>
    {% endif %}

{% endfor %}
13
votes

It sounds like you should just use the cycle tag. Built-in template tags