[Zope] Problem with _[xyz]

Martijn Pieters mj@digicool.com
Fri, 7 Jul 2000 21:01:16 +0200


On Fri, Jul 07, 2000 at 07:12:26PM +0200, Christian Zagrodnick wrote:
> shouldn't <dtml-var xyz> and <dtml-var "_['xyz']"> return the same result?
> 
> Well - I don't know why but only the 1st is working.
> (top.German.ActualPages is a folder; tThisIs... is a dtml-method)
> 
> 1:
> <dtml-with "top.German.ActualPages">
> <dtml-var tThisIsTheXYZDocument>
> </dtml-with>
> 
> 
> 2:
> <dtml-with "_['top.German.ActualPages']">
> <dtml-var tThisIsTheXYZDocument>
> </dtml-with>
> 
> 
> Of course I want to replace the 'top.German.ActualPages' with a variable...
> but since it doesn't work with a hardcoded string it'll not work with a
> variable.

Two things wrong here:

1. <dtml-var expr="xyz"> is not the same as <dtml-var expr="_['xyz']"> if xyz is
   callable! <dtml-var name="xyz"> (or <dtml-var xyz>) however is. 
   
   _[] will call the identified object if it can be. You can use
   _.getitem('xyz', 0) (or just plain _.getitem('xyz')) to get an item without
   calling it. Calling _.getitem('xyz', 1) (second argument 'true') is the
   same as _['xyz'] and <dtml-var xyz> again.

2. top.German.ActualPages is a Python expression meaning "The 'ActualPages'
   object in the 'German' object inside the 'top' object. The '.' operator
   signifies containment or membership.

   _['top.German.ActualPages'] however, means "The 'top.German.ActualPages'
   object", where the dots are part of the identifier. You want to split this
   name up at the dots, and ask the namespace for each part individually, like
   _['top']['German']['ActualPages'].

Now, using a variable, this is going to be a bit more tricky. If it is all the
same to you, you may want to change such an object pointer to use '/' instead
of '.' as an object delimiter, and use the new Zope 2.2.0 Traversal interface
for this. If you have to, you use _.string.replace to replace all dots with
slashes on the spot. For this interface, see:

  http://www.zope.org/Members/michel/Projects/Interfaces/Traversal

Note that this interface is restricted to Product and External Method access
only! You will have to create yourself a Eternal Method in this case:

    import string

    getObject(self, id):
        if string.find(id, '.'): id = string.split(id, '.')
        return self.restrictedTraverse(id)

The above method will support id's with both dots and slashes, but not id's
that have a '.' in them (like 'image.gif').

Use this method then like this:

  <dtml-with "getObject(id)">
    <dtml-var tThisIsTheXYZDocument>
  </dtml-with>

-- 
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
-----------------------------------------------------