[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