Switched contentlets to use lists rather than sets to preserve ordering. Resolves...
authorStephen Burrows <stephen.r.burrows@gmail.com>
Wed, 1 Jun 2011 17:47:39 +0000 (13:47 -0400)
committerStephen Burrows <stephen.r.burrows@gmail.com>
Wed, 1 Jun 2011 17:47:39 +0000 (13:47 -0400)
philo/admin/forms/containers.py
philo/models/pages.py
philo/tests.py

index 246a954..987524f 100644 (file)
@@ -153,7 +153,7 @@ class ContainerInlineFormSet(BaseInlineFormSet):
 class ContentletInlineFormSet(ContainerInlineFormSet):
        def get_containers(self):
                try:
-                       containers = list(self.instance.containers[0])
+                       containers = self.instance.containers[0]
                except ObjectDoesNotExist:
                        containers = []
                
index bdd9b42..0ce047e 100644 (file)
@@ -4,6 +4,8 @@
 
 """
 
+import itertools
+
 from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes import generic
@@ -30,7 +32,7 @@ class LazyContainerFinder(object):
        def __init__(self, nodes, extends=False):
                self.nodes = nodes
                self.initialized = False
-               self.contentlet_specs = set()
+               self.contentlet_specs = []
                self.contentreference_specs = SortedDict()
                self.blocks = {}
                self.block_super = False
@@ -47,7 +49,7 @@ class LazyContainerFinder(object):
                        
                        if isinstance(node, ContainerNode):
                                if not node.references:
-                                       self.contentlet_specs.add(node.name)
+                                       self.contentlet_specs.append(node.name)
                                else:
                                        if node.name not in self.contentreference_specs.keys():
                                                self.contentreference_specs[node.name] = node.references
@@ -78,6 +80,26 @@ class LazyContainerFinder(object):
                        self.initialized = True
 
 
+def build_extension_tree(nodelist):
+       nodelists = []
+       extends = None
+       for node in nodelist:
+               if not isinstance(node, TextNode):
+                       if isinstance(node, ExtendsNode):
+                               extends = node
+                       break
+       
+       if extends:
+               if extends.nodelist:
+                       nodelists.append(LazyContainerFinder(extends.nodelist, extends=True))
+               loaded_template = getattr(extends, LOADED_TEMPLATE_ATTR)
+               nodelists.extend(build_extension_tree(loaded_template.nodelist))
+       else:
+               # Base case: root.
+               nodelists.append(LazyContainerFinder(nodelist))
+       return nodelists
+
+
 class Template(TreeModel):
        """Represents a database-driven django template."""
        #: The name of the template. Used for organization and debugging.
@@ -97,35 +119,16 @@ class Template(TreeModel):
                """
                template = DjangoTemplate(self.code)
                
-               def build_extension_tree(nodelist):
-                       nodelists = []
-                       extends = None
-                       for node in nodelist:
-                               if not isinstance(node, TextNode):
-                                       if isinstance(node, ExtendsNode):
-                                               extends = node
-                                       break
-                       
-                       if extends:
-                               if extends.nodelist:
-                                       nodelists.append(LazyContainerFinder(extends.nodelist, extends=True))
-                               loaded_template = getattr(extends, LOADED_TEMPLATE_ATTR)
-                               nodelists.extend(build_extension_tree(loaded_template.nodelist))
-                       else:
-                               # Base case: root.
-                               nodelists.append(LazyContainerFinder(nodelist))
-                       return nodelists
-               
                # Build a tree of the templates we're using, placing the root template first.
-               levels = build_extension_tree(template.nodelist)[::-1]
+               levels = build_extension_tree(template.nodelist)
                
-               contentlet_specs = set()
+               contentlet_specs = []
                contentreference_specs = SortedDict()
                blocks = {}
                
-               for level in levels:
+               for level in reversed(levels):
                        level.initialize()
-                       contentlet_specs |= level.contentlet_specs
+                       contentlet_specs.extend(itertools.ifilter(lambda x: x not in contentlet_specs, level.contentlet_specs))
                        contentreference_specs.update(level.contentreference_specs)
                        for name, block in level.blocks.items():
                                if block.block_super:
@@ -136,7 +139,7 @@ class Template(TreeModel):
                for block_list in blocks.values():
                        for block in block_list:
                                block.initialize()
-                               contentlet_specs |= block.contentlet_specs
+                               contentlet_specs.extend(itertools.ifilter(lambda x: x not in contentlet_specs, block.contentlet_specs))
                                contentreference_specs.update(block.contentreference_specs)
                
                return contentlet_specs, contentreference_specs
index 5a9a5ba..15ce752 100644 (file)
@@ -3,11 +3,13 @@ import traceback
 
 from django import template
 from django.conf import settings
+from django.contrib.contenttypes.models import ContentType
 from django.db import connection, models
 from django.template import loader
 from django.template.loaders import cached
 from django.test import TestCase
 from django.test.utils import setup_test_template_loader, restore_template_loaders
+from django.utils.datastructures import SortedDict
 
 from philo.exceptions import AncestorDoesNotExist
 from philo.models import Node, Page, Template, Tag
@@ -200,3 +202,17 @@ class TreePathTestCase(TestCase):
                self.assertQueryLimit(1, 'second/third', root, callable=third.get_path)
                self.assertQueryLimit(1, e, third, callable=second2.get_path)
                self.assertQueryLimit(1, '? - ?', root, ' - ', 'title', callable=third.get_path)
+
+
+class ContainerTestCase(TestCase):
+       def test_simple_containers(self):
+               t = Template(code="{% container one %}{% container two %}{% container three %}{% container two %}")
+               contentlet_specs, contentreference_specs = t.containers
+               self.assertEqual(len(contentreference_specs.keyOrder), 0)
+               self.assertEqual(contentlet_specs, ['one', 'two', 'three'])
+               
+               ct = ContentType.objects.get_for_model(Tag)
+               t = Template(code="{% container one references philo.tag as tag1 %}{% container two references philo.tag as tag2 %}{% container one references philo.tag as tag1 %}")
+               contentlet_specs, contentreference_specs = t.containers
+               self.assertEqual(len(contentlet_specs), 0)
+               self.assertEqual(contentreference_specs, SortedDict([('one', ct), ('two', ct)]))