[Zope-dev] Acquisition in a DTML Tag

Martijn Pieters mj@digicool.com
Tue, 12 Sep 2000 20:24:05 +0200


On Tue, Sep 12, 2000 at 10:57:57AM -0700, Brett Carter wrote:
> >>>>> "Shane" == Shane Hathaway <shane@digicool.com> writes:
> 
>     Shane> Brett Carter wrote:
>     >>  >>>>> "Brett" == Brett Carter <brett@kavi.com> writes:
>     >> 
>     Brett> I've defined my own dtml tag (i.e. <dtml-foo></dtml-foo>)
>     Brett> and I am trying to look up an object depending on the
>     Brett> arguments passed to my tag.  The python class that defines
>     Brett> the tag inherits from Acquisition.Implicit, but 'self'
>     Brett> doesn't contain any of the Acquisition hiarchy.  It seems
>     Brett> like this must be possible, since the <dtml-var> tag must
>     Brett> have to do an object lookup somewhere for objects passed to
>     Brett> it to render.  Can anybody shed some light on this?  Is it
>     Brett> doable?  TIA -Brett
>     >>  Ok, So after some *major* hacking, i've realized that the 'md'
>     >> passed into the render() method of my dtml tag contains the
>     >> namespace, and is of type 'TemplateDict' which appears to
>     >> contain a stack of 'MultiMapping's.  Weird.  Well, anyways, I
>     >> just used the 'has_key' and 'getitem' methods to lookup my
>     >> item.  The question now is how do I create a new object in the
>     >> current namespace?  It looks like the TemplateDict is a
>     >> read-only type of data structure.  Anybody?  TIA -Brett
> 
>     Shane> Look at render() of DT_With.py.  It does an
>     Shane> md._push(<mapping containing new names>) then, in a
>     Shane> try/finally clause, calls DT_Util.render_blocks().  In the
>     Shane> finally clause, it does md._pop().
> 
>     Shane> Shane
> 
> I'm still confused.  Ok, so render gets passed 'md', which is a
> TemplateDict, which contains a MultiMapping, which looks like a stack
> of dictionaries, which I am guessing is some sort of namespace stack.
> So looking at the DT_with.py, it looks like, to create an object in
> the current namespace, I have to wrap it in an InstanceDict, and push
> it onto the 'md' using 'md._push'.  Does this also cause the new
> object to be saved in the ZODB?  Or do I have to manually add it there
> too?  Also, what does render_blocks do?  Why does DT_with.py's
> render() return it?  Do I have to run render_blocks() to insert my new
> object into the namespace?  TIA

There are two seperate things here: The namespace, and the ZODB. I am
assuming you want to add an object to the ZODB.

The namespace reflects, amongst others, the attributes on the current
object, and if it inherits from Acquisition.Implicit, the rest of the
ZODB contents. You can add additional lookup objects to that stack, and
anything using the namespace can then access those extra attributes.

(render_blocks() is just a call to render all DTML contained within the
with tag, and the with tag then removes all additions to the namespace
again with md._pop() at the end.)

If you want to manipulate the ZODB, you can just take a reference to the
object you want to manipulate (add subobjects to), and add these directly
as attributes. Or better still, if the object inherits from ObjectManager
(like a Folder), use the ObjectManager API to add objects. If the
subobjects in question are standard Zope objects, use the Class Factory
API that the 'Add' list in the management interface uses.

Important to remember is here that the namespace only gives you access to
the objetcs. Adding to the namespace only gives you a larger namespace,
which only has meaning in the context of the current DTML code tree. If
you want to manipulate the ZODB contained objects, manipulate them
directly.

-- 
Martijn Pieters
| Software Engineer            mailto:mj@digicool.com
| Digital Creations          http://www.digicool.com/
| Creators of Zope               http://www.zope.org/
| ZopeStudio: http://www.zope.org/Products/ZopeStudio
-----------------------------------------------------