[Fixed]-Render one queryset into 2 div columns (django template)

16๐Ÿ‘

โœ…

I recommend using Django filters.

Django snippets provides a partitioning template filter, which you can use like:

{% load listutil %}

<div class="grid_8 alpha">
    {% for sport in sports|partition:"2"|first %}
        <!-- Blah Blah -->
    {% endfor %}
</div>

<div class="grid_8 omega">
    {% for sport in sports|partition:"2"|last %}
        <!-- Blah Blah -->
    {% endfor %}
</div>
๐Ÿ‘คnotnoop

6๐Ÿ‘

  1. This is the task of a rendering system, not view. The view should not know whether you will display 2, 3 or 4 columns in your template.
  2. It is always better to use default Django tags.

Use default Django template tag cycle:

<table>
    {% for item in items %}
        {% cycle 'row' '' as row silent %}
        {% if row %}<tr>{% endif %}
            <td>
                {{ item }}
            </td>
        {% if not row %}</tr>{% endif %}
    {% endfor %}
</table>

It will display your list [1 2 3 4 5 6] as

1 2

3 4

5 6

By the way, Jinja2 template engine has batch and slice filters which will do the trick. I switched to jinja2 and now have none of those problems of โ€œhow to display x using poor django tags and filtersโ€

๐Ÿ‘คMrKsn

1๐Ÿ‘

I think you will have to make your own template tag to do splits on queries. I would do something like.

from django.template import Library, Node, TemplateSyntaxError
from restaurants.forms import MenuItemForm

class Split(Node):
    def __init__(self, queryset, split_count=2, basename=None):
        self.queryset_name = queryset
        self.split_count = split_count
        self.basename = basename if basename else queryset

    def render(self, context):
        qs = context[self.queryset_name]
        qs_break = len(qs)/self.split_count
        for x in xrange(0, self.split_count-1):
            context["%s_%i"%(self.basename, x+1)] = qs[qs_break*x:qs_break*(x+1)]
        context["%s_%i"%(self.basename, x+2)] = qs[qs_break*x+1:]
        return ''        



def split(parser, token):
    """
    Call from template will be
    {% split <queryset> on <count> as <name> %}
    """
    tokens = token.split_contents()
    if len(tokens) > 6:
        raise TemplateSyntaxError("Too many Tokens")
    #Do various tests to make sure it's right.
    return Split(tokens[1], tokens[3], tokens[5])

split = register.tag(split)

Please note that I havenโ€™t actually tested this code, so it might fail spectacularly, but it should point you towards the right direction for getting that stuff out of your view.

๐Ÿ‘คemeryc

0๐Ÿ‘

Hereโ€™s a quick solution which uses bootstrap and needs no Django filters

<div class="row">
    {% for sport in sports %}
        <div class="col-md-6">
            <!-- Blah Blah -->
        </div>
    {% endfor %}
</div>

0๐Ÿ‘

Late response, pretty much 13 years later ๐Ÿ™‚ but I think the easiest way if you have a fixed length list is to follow the same approach you used in your example, just slice the list. But thereโ€™s no need to slice on the view, you can slice on the template using the slice filter.

<div class="grid_8 alpha">
    {% for sport in sports|slice:":7" %}
        <!-- Blah blah -->
    {% endfor %}
</div>

<div class="grid_8 omega">
    {% for sport in sports|slice:"7:" %}
        <!-- Blah blah -->
    {% endfor %}
</div>

Note: If you donโ€™t have a fixed size list you will probably need to check out the length filter (sports|length) and find a way to divide in Django templates. But at that point is probably better to create your own filter following @notnoop response.

๐Ÿ‘คCesar Lopez

Leave a comment