Render one queryset into 2 div columns (django template)
Asked Answered
I

5

17

Is there a good way to render the enumeration of a queryset into two div columns?

Using 960 grid, I've got something to the effect of...

<div class="container_16">
    <div class="grid_8 alpha"></div>
    <div class="grid_8 omega"></div>
</div>

In Django, one model needs to have it's enumerated contents rendered in both of those columns, and preferably somewhat equally. For the moment, I've got some ugly code that in the view splits the QuerySet into 2 halves, and then each half is rendered in their respective column.

There's got to be a better way to do this, preferably using only the template rendering system?

Just for reference, here's how it "works" at the moment:

views.py

@render_to('template.html')
def main_athletics_page(request, *args, **kwargs):    
    sports = Sport.objects.all()
    half = sports.count() / 2
    return { 'sports_1' : sports[0:half], 'sports_2' : sports[half:] }

template.html

<div class="grid_8 alpha">
    {% for sport in sports_1 %}
        <!-- Blah blah -->
    {% endfor %}
</div>

<div class="grid_8 omega">
    {% for sport in sports_2 %}
        <!-- Blah blah -->
    {% endfor %}
</div>
Illjudged answered 22/10, 2009 at 21:49 Comment(0)
P
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>
Paternalism answered 22/10, 2009 at 22:24 Comment(1)
Clever filter! This is the direction I was wanting to go.Illjudged
S
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"

Scrapple answered 13/10, 2014 at 6:38 Comment(0)
M
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.

Mapel answered 22/10, 2009 at 22:25 Comment(0)
D
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>
Disposition answered 25/4, 2014 at 19:21 Comment(1)
This is not what he wants. He wants some items in one column and the rest in another column. Your soultion will put each item in a column.Mossman
I
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.

Irritable answered 30/8, 2022 at 17:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.