[Zope] Re: accessing objects in subfolders

Danny William Adair danny@adair.net
Mon, 29 Oct 2001 18:51:04 +1300


Hi Steve!

On Thursday 18 October 2001 20:47, you wrote:
> Hi Danny - thanks for you reply,
> ...
>
> On a different (but connected) matter I'm really puzzled by that following.
>
> if nodename="French"
>
> <dtml-with expr="_.getitem(nodename,1)"> works fine
>
> but if nodename="French.Folder1"
>
> <dtml-with expr="_.getitem(nodename,1)"> doesn't work!
>
> but if I specify the path as a literal it does work
>
> <dtml-with expr="French.Folder1">
>
> In the interests of my receding hairline, can you offer any explanation?
> (I was hoping to use many levels of folders)
>
> Many thanks
>
> Steve

Sorry for answering so late. Just in case you haven't found out by now:
;-)

That's happening because "getitem" expects an object id (not a complete path) 
as a parameter. There is no object with the id "French.Folder1" in the 
namespace. What you want to do is traverse to an object, given its path as a 
string parameter. There are two built-in functions that do that, 
"restrictedTraverse" and "unrestrictedTraverse". unrestrictedTraverse will 
bring you to an object even if there are objects "on the way" that you are 
not allowed to access. "restrictedTraverse" on the other hand (usually the 
preferred one) will check for sufficient rights on every object along the 
path. Afaik, these two functions take the object's path as a string 
parameter, where the object ids themselves are separated by slashes.

Try this out:

Create a python script "goto" :-o holding this single line:
(parameter: path)
---------------------------------------
return context.restrictedTraverse(path)
---------------------------------------

Now you should be able to get to your "subfolder object" by calling:

<dtml-with expr="goto(nodename)">

Keep in mind that this time your object ids have to be separated by a slash 
(e.g. "French/Folder")

If you want the same functionality with dots (because you have already set up 
everything to work "the dot way" :-)), you would change the script to:
(parameter: path)
---------------------------------------
from string import replace
path_to_object = replace(path, '.', '/')
return context.restrictedTraverse(path_to_object)
---------------------------------------
There's one obvious problem with this: you can't use dots in an id. But this 
should only be the case with old - imported - *.html files, anyway...

(un)restrictedTraverse will start "getiteming" the specified object ids 
starting from the object you called the function on. So if you only need this 
functionality in your (folderish) "Lang" object for example, you could put 
the script in there and change "context.restrictedTraverse" to 
"container.restrictedTraverse". Then the traversal will always start in 
"Lang". This way you will also avoid conflicts with other objects having the 
same ids. Let's say you have the following directory structure:

/-+-Lang-+-English
         +-French-+-Folder
                  +-Folder2-+-Folder-+-French-+-myObject
                                              +-...
                                     +-...
                            +-...
                  +-...
         +-goto (Python Script)

In this case, the "context.restrictedTraverse()" version might not do what 
you intended when you call "myObject", because after finding "French" - too 
early - it will find the wrong "Folder", where you might be expecting 
something that's not there... Here, the "container.restrictedTraverse()" 
version would be the better choice. "container" will _always_ be the 
_script's_ container, no matter where the script is called from.

On the other hand, this "context" behavior might as well be exactly what you 
want to happen... :-)

Hope this helps,
Danny

P.S.: I've CCed this to the Zope mailing list, cos I thought it might of 
interest for others with similar problems.