Thanks for your reply, I really like the general iterator approach. This recipe will definitely go to my personal "standard" library.
A. On Dec 2, 11:09 pm, Tim Chase <[EMAIL PROTECTED]> wrote: > > If your data is in the 'data' context variable, then try this: > > > <table> > > {% for d in data %} > > {% if forloop.counter0|divisibleby:"2" %}<tr>{% endif %} > > <td>{{d}}</td> > > {% if forloop.counter|divisibleby:"2" %}</tr>{% endif %} > > {% endfor %} > > {% if data|length|divisibleby:"2" %}{% else > > %}<td> </td></tr>{% endif %} > > </table> > > > It's a little awkward, and doesn't generalize to more than two columns, > > but it does produce properly structured HTML. > > It can be generalized, as I've done it in a pinch, and it looks > something like this (untested, as I don't have my actual code > right in front of me): > > <table> > <tr> > {% for d in data %} > <td>{{d}}</td> > {% if forloop.counter|divisibleby:"4" %}</tr><tr>{% endif %} > {% endfor %} > </tr> > </table> > > HTML is forgiving if you don't have the right number of columns > in your final row (don't know about XHTML's definition). And it > adds a bogus row at the bottom if your dataset is divisible by N. > > A better way would be to make a custom template filter that > breaks the data-set into groups. > > ##################################### > from itertools import izip, islice > > def pad(iterable, length, padding=None): > i = 0 > for thing in iterable: > i += 1 > yield thing > for i in xrange(length - i): > yield padding > > def columnize(dataset, args="2"): > if "," in str(args): > columns, padding = args.split(",",1) > else: > columns = args > padding = "" > columns = int(columns) > row_count, leftovers = divmod(len(dataset), columns) > if leftovers: row_count += 1 > return izip(*( > pad(islice(dataset, i, None, columns), row_count, padding) > for i in xrange(columns) > )) > ##################################### > > and then register columnize your filter. It should presume 2 > columns, but be extensible to more than two columns with an > optional parameter. It also takes optional padding as a > parameter, so it can be called like > > <table> > {% for thing in data|columnize:"3, " %} > <tr> > {% for value in thing %} > <td>{{ value }}</td> > {% endfor %} > </tr> > {% endfor %} > </table> > > or > > <table> > {% for thing in my_queryset|columnize %} > <tr> > {% for value in thing %} > <td> > {% if value %} > <b>{{ value.name }}:</b> > {{ value.other_field }} > {% else %} > > {% endif %} > </td> > {% endfor %} > </tr> > {% endfor %} > </table> > > which is about as clean a solution as it gets, as it guarantees > "square" result-sets that have been padded out. > > -tim --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---