开发者

Using Zope object unique id ( _p_oid ) to access object itself

开发者 https://www.devze.com 2022-12-25 14:29 出处:网络
Every Zope object has it\'s own unique id ( _p_oid ). To convert it into integer value: from Shared.DC.xml.ppml import u64 as decodeObjectId

Every Zope object has it's own unique id ( _p_oid ).

To convert it into integer value:

from Shared.DC.xml.ppml import u64 as decodeObjectId
oid = decodeObjectId(getattr(<Object in开发者_开发问答stance>, '_p_oid'))

Is it possible to get object itself having it's _p_oid?

I tried this:

from ZODB.utils import p64
object = <RootObject instance>._p_jar[p64(oid)]

But it seems it's a wrong way because after getting object I can't change any property and object.absolute_url() returns empty string.


This should work, as long as the class of the object you're trying to load is available in the Python environment, and as long as your oid isn't from another database mounted somewhere within the root.

Can you describe the way in which this is failing to work for you?

See whether the following works (it should get the root object, which has _p_oid == 0):

>>> object = root_obj._p_jar[p64(0)]


You can access the object just fine that way, but you get an unwrapped object.

In Zope, the object is normally retrieved via traversal, and every next object you retrieve this way is wrapped in the correct acquisition context. This context tells every object what it's parent object is, and this is in turn used to calculate the object's absolute URL and it's security context.

You would be better off using the Zope intid facilities (via it's five.intid integration layer); that gives you a unique integer ID for each object, and the utility not only keeps track of the object but also of it's path, so you can get the object back with the correct context.


As far as I know, the correct way to do it is to use the get method of the connection instance:

>>> db = DB(...)
>>> conn = db.open()
>>> obj = conn.get(oid)

EDIT: it seems that dbroot._p_jar is an ZODB.Connection.Connection object just like the return type of db.open() so perhaps it can be assumed that both ways are equivalent. Arguably, conn.get(...) seems cleaner as it does not involve accessing underscore-prefixed methods.

0

精彩评论

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