开发者

unrestrictedTraverse gets the wrong object when there is two adjacent identical ids

开发者 https://www.devze.com 2023-03-18 22:46 出处:网络
I have: try: path1 = /Plone/s/a path2 = 2011/07/07 #The path to traverse becomes /Plone/s/a/2011/07/07/. From

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消