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

Steve Schmechel steveschmechel at yahoo.com
Fri Mar 27 18:05:25 EDT 2009


I will try to cover this topic in the tutorial I am writing.
I want to post back what I ended up doing here, in case someone else finds this thread during a search.

The class holding the two containers ended up looking like this:

class Performance(grok.Container):
    interface.implements(IPerformance)  #Only affects display of
    location = u''                      #fields on forms.  Template
    leader = u''                        #must handle containers.
    def __init__(self):
        super(Performance, self).__init__()  #See note below.
        self['musicians'] = Musicians() #Inherits from grok.Container
        self['songs'] = Songs()         #Inherits from grok.Container

Note:  The "super(Performance, self).__init__()" line had to be added in order for this to work.  

I won't attempt to go into the reason why, as others much more knowledgeable than myself have discussed this in depth.  
(If you are interested see: 
http://mail.zope.org/pipermail/grok-dev/2008-October/006509.html
and 
https://bugs.launchpad.net/grok/+bug/162286 )

Another thing to remember is that page templates may have to handle this collection slightly differently.  The "context/musicians" style references seems to work the same as with fields, but "python:" dotted notations will have to follow the proper Python syntax.  

So, if you had used it as a dictionary-type field, like this:
   python:context.musicians.keys()

It will have to change to something like:
   python:context['musicians'].keys()

Partial example of how to get a list of the contained Musician objects:
 <tal:block repeat="name python:context['musicians'].keys()">

Thanks again for the help Leo.

--- On Fri, 3/27/09, Steve Schmechel <steveschmechel at yahoo.com> wrote:

> From: Steve Schmechel <steveschmechel at yahoo.com>
> Subject: Re: [Grok-dev] Containers with different object types and traversal
> To: "Leonardo Rochael Almeida" <leorochael at gmail.com>
> Cc: "Grok list" <grok-dev at zope.org>
> Date: Friday, March 27, 2009, 2:27 PM
> --- On Fri, 3/27/09, Leonardo Rochael Almeida
> <leorochael at gmail.com> wrote:
> 
> > Hi Steve,
> > 
> > Please keep the conversation in the list.
> 
> Sorry.  Not intentional.  I hit the wrong button when
> replying.
> 
> > 
> > The subcontainers should be instances of (subclasses
> of)
> > grok.Container, and traversal should just work after
> you
> > add it to the
> > "performance" container, just like it does
> for
> > instances of Model
> > subclasses.
> 
> I think I see what I did wrong.  I changed
> "performance" back to being an instance of
> grok.Model instead of leaving it as an instance of
> grok.Container.
> 
> "It is a container simply so that it can hold the
> other containers."
> 
> I will eventually get my head around this. 
> 
> Thanks so much for your help!
> 
> > 
> > Without looking at your code it's a little
> difficult to
> > know what went
> > wrong in your case.
> > 
> > Cheers, Leo
> > 
> > On Fri, Mar 27, 2009 at 16:02, Steve Schmechel
> > <steveschmechel at yahoo.com> wrote:
> > >
> > > How do you get these subclasses to play nice with
> > traversal?
> > > Do the __parent__ and __name__ fields need to be
> set
> > manually?
> > >
> > > The application gives me a "page not
> found"
> > and, when I try to inspect the objects using the Grok
> Admin
> > UI, I get:
> > >
> > >
> >
> http://localhost:8080/docgrok-obj/band/2009-03-15/musicians/@@inspect.html
> > > ...
> > > TypeError: ('Not enough context information
> to get
> > parent', <music.musician.Musicians object at
> > 0x36ce2a8>)
> > >
> > > Thanks,
> > > Steve
> > >
> > > --- On Fri, 3/27/09, Leonardo Rochael Almeida
> > <leorochael at gmail.com> wrote:
> > >
> > >> From: Leonardo Rochael Almeida
> > <leorochael at gmail.com>
> > >> Subject: Re: [Grok-dev] Containers with
> different
> > object types and traversal
> > >> To: steveschmechel at yahoo.com
> > >> Cc: grok-dev at zope.org
> > >> Date: Friday, March 27, 2009, 12:23 PM
> > >> Hi Steve,
> > >>
> > >> It seems to me that the simplest way to
> accomplish
> > what you
> > >> want is to
> > >> put two (subclasses of) Containers inside
> your
> > Performance
> > >> instance,
> > >> called "musicians" and
> > "songs". Inside
> > >> each of these sub-containers
> > >> you would then place, respectively, your
> musician
> > and song
> > >> instances.
> > >>
> > >> You could use either the __init__ of your
> > Performance class
> > >> or a
> > >> subscriber to ObjectAddedEvent that matched
> > against your
> > >> Performance
> > >> instance to create your sub-folders.
> > >>
> > >> This would give you the URLs you wish.
> > >>
> > >> Cheers, Leo
> > >>
> > >> On Fri, Mar 27, 2009 at 13:05, Steve
> Schmechel
> > >> <steveschmechel at yahoo.com> wrote:
> > >> >
> > >> > 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
> > >> >
> > >> >
> > >> >
> > >> >
> > _______________________________________________
> > >> > Grok-dev mailing list
> > >> > Grok-dev at zope.org
> > >> >
> > http://mail.zope.org/mailman/listinfo/grok-dev
> > >> >
> > >
> > >
> > >
> > >
> 
> 
>       
> _______________________________________________
> Grok-dev mailing list
> Grok-dev at zope.org
> http://mail.zope.org/mailman/listinfo/grok-dev


      


More information about the Grok-dev mailing list