unrestrictedTraverse gets the wrong object when there is two adjacent identical ids
I have:
try:
path1 = /Plone/s/a
path2 = 2011/07/07
#The path to traverse becomes /Plone/s/a/2011/07/07/. From
#Plone to 开发者_Go百科last 07, they are normal Folders.
ob = self.portal.unrestrictedTraverse('%s/%s/' % (path1, path2))
print ob
except AtributeError:
#do something
pass
/Plone/s/a/2011/07/07/ doesn't exist. /Plone/s/a/2011/07/ exists. The code above is supposed to give an AtributeError, but I get /Plone/s/a/2011/07/ object instead. It prints:
<ATFolder at /Plone/s/a/2011/07 used for /Plone/s/a/2011/07>
I don't want to get a "similar" result from the traverse, this is wrong. I need specifically /Plone/s/a/2011/07/07/. If it doesn't exists, I want to catch the exception .
Which other approaches can I use to see if there's an object exactly at /Plone/s/a/2011/07/07/, and not close enough like /Plone/s/a/2011/07/?
You hit acquisition.
You want to get the '07' element/property/attribute of the '07' folder. But this last one doesn't have a sub-object with that id. So , due to acquisition, the existing '07' folder asks to its parent element if it has a sub-object with the mentioned id, and of course, '2011' folder has that element, the '07' one you are sitting on.
This is a rough explanation of how acquisition works.
Another example is this URL: http://plone.org/news/news/news/news/news/events
The 'events' folder doesn't really live in 'news' folder. And all those 'news' folders aren't really there, but there is at least one 'news' folder living in plone.org root, and although it doesn't have an 'events' folder, its parent (plone.org again) does.
Here you have some references:
- http://plone.org/documentation/glossary/acquisition
- http://docs.zope.org/zope2/zope2book/Acquisition.html
If you want to make sure an element/property/attribute is really part of the parent element you should use aq_base
from Acquisition
:
from Acquisition import aq_base
plone = aq_base(self.portal.Plone)
s = aq_base(getattr(plone, 's'))
a = aq_base(getattr(s, 'a'))
year = aq_base(getattr(a, '2011'))
month = aq_base(getattr(year, '07'))
day = aq_base(getattr(month, '07'))
aq_base
strips the acquisition chain from the element so no acquisition will be used to get its elements.
精彩评论