From adbb2ab3e867579291a8ad464ff559334d6b5eb4 Mon Sep 17 00:00:00 2001 From: Stephen Burrows Date: Wed, 22 Jun 2011 12:30:25 -0400 Subject: [PATCH] Added memoization (optional but enabled by default) to TreeEntity.get_path. --- philo/models/base.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/philo/models/base.py b/philo/models/base.py index 2f798ae..d1dc38a 100644 --- a/philo/models/base.py +++ b/philo/models/base.py @@ -458,11 +458,12 @@ class TreeEntity(Entity, MPTTModel): objects = TreeEntityManager() parent = models.ForeignKey('self', related_name='children', null=True, blank=True) - def get_path(self, root=None, pathsep='/', field='slug'): + def get_path(self, root=None, pathsep='/', field='pk', memoize=True): """ :param root: Only return the path since this object. :param pathsep: The path separator to use when constructing an instance's path :param field: The field to pull path information from for each ancestor. + :param memoize: Whether to use memoized results. Since, in most cases, the ancestors of a TreeEntity will not change over the course of an instance's lifetime, this defaults to ``True``. :returns: A string representation of an object's path. """ @@ -476,12 +477,26 @@ class TreeEntity(Entity, MPTTModel): if root is not None and not self.is_descendant_of(root): raise AncestorDoesNotExist(root) + if memoize: + memo_args = (getattr(self, "%s_id" % self._mptt_meta.parent_attr), getattr(root, 'pk', None), pathsep, getattr(self, field, '?')) + try: + return self._path_memo[memo_args] + except AttributeError: + self._path_memo = {} + except KeyError: + pass + qs = self.get_ancestors(include_self=True) if root is not None: qs = qs.filter(**{'%s__gt' % self._mptt_meta.level_attr: root.get_level()}) - return pathsep.join([getattr(parent, field, '?') for parent in qs]) + path = pathsep.join([getattr(parent, field, '?') for parent in qs]) + + if memoize: + self._path_memo[memo_args] = path + + return path path = property(get_path) def get_attribute_mapper(self, mapper=None): @@ -522,8 +537,8 @@ class SlugTreeEntity(TreeEntity): objects = SlugTreeEntityManager() slug = models.SlugField(max_length=255) - def get_path(self, root=None, pathsep='/', field='slug'): - return super(SlugTreeEntity, self).get_path(root, pathsep, field) + def get_path(self, root=None, pathsep='/', field='slug', memoize=True): + return super(SlugTreeEntity, self).get_path(root, pathsep, field, memoize) path = property(get_path) def clean(self): -- 2.20.1