1

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?

A.J.
  • 8,557
  • 11
  • 61
  • 89
  • If you want to do it the clever way you leave that problem to CSS. Make the inner container inline and the browser will fit as many images as possible into one row. It you don't like that, split the object list into chunks in the Python code before rendering the template. – Klaus D. Aug 01 '15 at 18:52
  • @Jack What solution did you end up using for this? – Matthew Lemieux Aug 02 '15 at 05:56
  • If found @Arnar Yngvason answer more simpler and comprehensive plus it did the job. – A.J. Aug 02 '15 at 08:19
  • If you find that question helpful, please +1 the question – A.J. Aug 02 '15 at 08:19

2 Answers2

1

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

Matthew Lemieux
  • 356
  • 3
  • 9
1

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 %}
Community
  • 1
  • 1
demux
  • 4,544
  • 2
  • 32
  • 56