Skip to content

Instantly share code, notes, and snippets.

@martync
Created March 26, 2013 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martync/5245814 to your computer and use it in GitHub Desktop.
Save martync/5245814 to your computer and use it in GitHub Desktop.
Template tag for Django : Regroup list of lists by index, exactly like the core {% regroup %} tag.
from itertools import groupby
from django import template
from django.template.base import TemplateSyntaxError
register = template.Library()
class RegroupListNode(template.Node):
def __init__(self, target, expression, var_name):
self.target, self.expression = target, expression
self.var_name = var_name
def render(self, context):
obj_list = self.target.resolve(context, True)
if obj_list is None:
# target variable wasn't found in context; fail silently.
context[self.var_name] = []
return ''
sortkeyfn = lambda s: s[0]
obj_list.sort(key=sortkeyfn)
result = []
for key, valuesiter in groupby(obj_list, key=sortkeyfn):
result.append(dict(grouper=key, list=list(valuesiter)))
context[self.var_name] = result
return ''
def regrouplist(parser, token):
"""
Just like `django.template.defaulttags.regroup`
but for list of lists.
Let's say i have these datas :
table_datas = [
['Mr', 'Jacques', 'CHIRAC'],
['Mr', 'Bill', 'CLINTON'],
['Mme', 'Carla', 'BRUNI AU SOLEIL']
]
I use this to regroup on index 0 :
{% regrouplist table_datas by 0 as gender_list %}
To get something like :
"Mr":
['Mr', 'Jacques', 'CHIRAC'],
['Mr', 'Bill', 'CLINTON'],
"Mme":
['Mme', 'Carla', 'BRUNI AU SOLEIL']
"""
firstbits = token.contents.split(None, 3)
if len(firstbits) != 4:
raise TemplateSyntaxError("'regrouplist' tag takes five arguments")
target = parser.compile_filter(firstbits[1])
if firstbits[2] != 'by':
raise TemplateSyntaxError("second argument to 'regrouplist' tag must be 'by'")
lastbits_reversed = firstbits[3][::-1].split(None, 2)
if lastbits_reversed[1][::-1] != 'as':
raise TemplateSyntaxError("next-to-last argument to 'regrouplist' tag must"
" be 'as'")
expression = parser.compile_filter(lastbits_reversed[2][::-1])
var_name = lastbits_reversed[0][::-1]
return RegroupListNode(target, expression, var_name)
regrouplist = register.tag(regrouplist)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment