A.J.
A.J.

Reputation: 9025

Bootstrap styling in Django

Mostly is see CSS / HTML in bootstrap we came across the following template.

    <div class="row">
      <div class="col-sm-6">
        # Add image/ or data you want
      </div>
      <div class="col-sm-6">
        # Add image/ or data you want
      </div>
    </div>

    # Second row

    <div class="row">
      <div class="col-sm-6">
        # Add image/ or data you want
      </div>
      <div class="col-sm-6">
        # Add image/ or data you want
      </div>
    </div>

How we can achieve this behavior in the Django templates? I mean when we are iterating over a list of values how we can keep track we need to start a new .row?

Dirty Solution

Check the loop iteration count and do integer manipulation to check if we new .row element should be started.

Thoughts?

Upvotes: 1

Views: 130

Answers (2)

demux
demux

Reputation: 4654

Create a template filter for splitting the list into chunks:

from django import template

register = template.Library()

@register.filter
def chunks(l, n):
    n = max(1, int(n))
    return (l[i:i+n] for i in xrange(0, len(l), n))

Usage:

{% for chunk in images|chunks:2 %}
    <div class="row">
        {% for image in chunk %}
            <div class="col-sm-6">
                # Add image/ or data you want
            </div>
        {% endfor %}
    </div>
{% endfor %}

You could also split the list into chunks before sending it to the template.

More on how to split lists into chunks here: How do you split a list into evenly sized chunks?

Custom filters for padding lists:

@register.filter
def ljust_list(l, n):
    """
    ljust_list([1, 2], 4) -> [1, 2, None, None]
    """
    return l + [None] * (n - len(l))

@register.filter
def rjust_list(l, n):
    """
    rjust_list([1, 2], 4) -> [None, None, 1, 2]
    """
    return [None] * (n - len(l)) + l

Usage:

{% for chunk in images|chunks:2 %}
    <div class="row">
        {% for image in chunk|ljust_list:2 %}
            <div class="col-sm-6">
                # Add image/ or data you want
            </div>
        {% endfor %}
    </div>
{% endfor %}

Upvotes: 1

Matthew Lemieux
Matthew Lemieux

Reputation: 356

This works:

{% for obj in objects %}
{% if not forloop.counter|divisibleby:2 and forloop.last %}
    <div class="row">
        <div class="col-md-6">
            {{ obj }}
        </div>
    </div>
{% elif not forloop.counter|divisibleby:2 %}
    <div class="row">
        <div class="col-md-6">
            {{ obj }}
        </div>
{% elif forloop.counter|divisibleby:2 %}
        <div class="col-md-6">
            {{ obj }}
        </div>
    </div>
{% endif %}
{% endfor %}

This solution uses Django built-in tags and filters. You may consider creating a custom tag, but that goes beyond the scope of the question.

Django: For Loop, Custom Tags

Upvotes: 1

Related Questions