From 2a34fbe043d5c4ba789e866a912646aea1bb807c Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Sun, 17 Jun 2007 07:33:18 +0000 Subject: [PATCH] Fixed #4506 -- Changed "regroup" template tag to use __eq__ instead of repr() for grouping equality checking. Thanks, Brian Harring. git-svn-id: http://code.djangoproject.com/svn/django/trunk@5484 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/template/defaulttags.py | 14 +++++--------- django/utils/itercompat.py | 24 +++++++++++++++++++++++- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 45005fa988..77fac6bec5 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -4,6 +4,7 @@ from django.template import Node, NodeList, Template, Context, resolve_variable from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END from django.template import get_library, Library, InvalidTemplateLibrary from django.conf import settings +from django.utils.itercompat import groupby import sys import re @@ -258,15 +259,10 @@ class RegroupNode(Node): if obj_list == None: # target_var wasn't found in context; fail silently context[self.var_name] = [] return () - output = [] # list of dictionaries in the format {'grouper': 'key', 'list': [list of contents]} - for obj in obj_list: - grouper = self.expression.resolve(obj, True) - # TODO: Is this a sensible way to determine equality? - if output and repr(output[-1]['grouper']) == repr(grouper): - output[-1]['list'].append(obj) - else: - output.append({'grouper': grouper, 'list': [obj]}) - context[self.var_name] = output + # List of dictionaries in the format + # {'grouper': 'key', 'list': [list of contents]}. + context[self.var_name] = [{'grouper':key, 'list':list(val)} for key, val in + groupby(obj_list, lambda v, f=self.expression.resolve: f(v, True))] return () def include_is_allowed(filepath): diff --git a/django/utils/itercompat.py b/django/utils/itercompat.py index 370988bedb..48a2d99d3a 100644 --- a/django/utils/itercompat.py +++ b/django/utils/itercompat.py @@ -7,7 +7,8 @@ these implementations if necessary. import itertools def compat_tee(iterable): - """Return two independent iterators from a single iterable. + """ + Return two independent iterators from a single iterable. Based on http://www.python.org/doc/2.3.5/lib/itertools-example.html """ @@ -25,7 +26,28 @@ def compat_tee(iterable): next = iter(iterable).next return gen(next), gen(next) +def groupby(iterable, keyfunc=None): + """ + Taken from http://docs.python.org/lib/itertools-functions.html + """ + if keyfunc is None: + keyfunc = lambda x:x + iterable = iter(iterable) + l = [iterable.next()] + lastkey = keyfunc(l) + for item in iterable: + key = keyfunc(item) + if key != lastkey: + yield lastkey, l + lastkey = key + l = [item] + else: + l.append(item) + yield lastkey, l + if hasattr(itertools, 'tee'): tee = itertools.tee else: tee = compat_tee +if hasattr(itertools, 'groupby'): + groupby = itertools.groupby