[Grok-dev] Containers with different object types and traversal

Steve Schmechel steveschmechel at yahoo.com
Fri Mar 27 12:05:16 EDT 2009


I know I once saw a complete list of rules for default traversal, but I can not seem to find it again.  Does anyone know where a list like that can be found?

I thought that traversal included looking for fields within an object that could be traversed.  For example, an object with a field that is a container of other objects could be traversed as:
/AppContainer/ObjectName/ContainerField/ContainedObjectName

Which would be handy if you had an object that had two fields that were containers of different sets of objects:
/AppContainer/ObjectName/OtherContainerField/OtherContainedObjectName

However, as I sure most of you know, this does not work by default.  It seems that to contain anything that is traversable (without employing a custom traverser), you need to use grok.Container.

I'll admit that it is taking me a while to get used to using containers as content objects with their own fields.  Maybe, I have spent too much time with relational databases and other object models where containers (data tables, collections, dictionaries, etc.) and the stuff they contain (data rows, simple objects, etc.) are worked with very differently.

So, I finally saw some documentation on traversal of nested containers (on the Repoze.bfg site).  Of course, this makes sense to me when I think about a Plone site with a folder that contains another folder.  But, in Plone, the folder was just a folder and you couldn't add much direct content except by specifying another object to be the default view that "covers up" the folder's URL.

I was happy to find that grok.Container objects work fine with schemas and autoforms.  It seems I just need to dump all of my various content types into one parent container.  As long as the keys do not collide, this should work.

I do have some questions about this arrangement.

How to I keep the key string from conflicting?  I do not want to create contrived names that end up in the URL.  What kind of schemes to people use to keep the different types of objects from colliding?  (I'm not specifically talking about the "NameChooser" concept, although it may play into the solution.)

Example:

I have a container object that represents a musical performance by a band.  It has a list of songs that will be performed and a set of musicians that will be playing that day.  I want to be able to have something like:

/SpecificPerformance/musicians/BrianWilson as the url of a model object that defines a musician object and the instrument being played at that performance.

Now, if the band in playing a song called "BrianWilson" (BNL fans will get this reference ;-), I would have:
/SpecificPerformance/songs/BrianWilson as the url of a model object that defines a song and it's arrangement and key for this performance.

Now, if these are going to be in the same container I need a way to tell them apart.  Do I do something with the keys like:
/Performance/musicians-BrianWilson
/Performance/songs-BrianWilson
This seems kind of ugly.

Do I have to use something like z3c.Traverser to get the URL back to the original form, but leave the keys as above?

Can I subclass grok.Container and an add another dictionary and expect traversal to still work?  

There seems to be something close to this in the tests for zope.traversing at:
http://svn.zope.org/zope.traversing/trunk/src/zope/traversing/tests/test_traverser.py?rev=96010&view=auto

Where:

    def testTraversingDictSeesDictAPI(self):
        adict = {
            'foo': 'bar',
            'anotherdict': {'bar': 'foo'},
            'items': '123',
            }
        tr = Traverser(adict)
        self.assertEqual(tr.traverse('items'), adict.items)
        self.assertEqual(tr.traverse('anotherdict/bar'), 'foo')
        self.assertEqual(tr.traverse('anotherdict/items'),
                         adict['anotherdict'].items)

It looks like, if you had another dictionary in the object, you could traverse to that also.  This would basically accomplish what I wanted to do in the first place, but by modifying a component rather than simply arranging them in a particular way.

Has anyone done something like this?

Any feedback is welcome.

Thanks,
Steve


      


More information about the Grok-dev mailing list