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