Использование уникального идентификатора объекта Zope ( _p_oid ) для доступа к самому объекту

Каждый объект Zope имеет свой уникальный идентификатор ( _p_oid ).

Чтобы преобразовать его в целочисленное значение:

from Shared.DC.xml.ppml import u64 as decodeObjectId
oid = decodeObjectId(getattr(<Object instance>, '_p_oid'))

Можно ли получить сам объект с _p_oid?

Я пробовал это:

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

Но кажется, что это неправильный путь, потому что после получения объекта я не могу изменить какое-либо свойство, а object.absolute_url() возвращает пустую строку.


person Alex M    schedule 06.04.2010    source источник


Ответы (3)


Это должно работать, пока класс объекта, который вы пытаетесь загрузить, доступен в среде Python, и пока ваш oid не из другой базы данных, смонтированной где-то в корне.

Можете ли вы описать, как это не работает для вас?

Посмотрите, работает ли следующее (он должен получить корневой объект, у которого _p_oid == 0):

>>> object = root_obj._p_jar[p64(0)]
person David Glick    schedule 15.04.2010

Таким образом вы можете получить доступ к объекту, но вы получите развернутый объект.

В Zope объект обычно извлекается путем обхода, и каждый следующий объект, который вы извлекаете таким образом, помещается в правильный контекст получения. Этот контекст сообщает каждому объекту, что является его родительским объектом, и это, в свою очередь, используется для вычисления абсолютного URL-адреса объекта и его контекста безопасности.

Вам лучше использовать средства Zope intid (через его five.intid слой интеграции); это дает вам уникальный целочисленный идентификатор для каждого объекта, и утилита отслеживает не только объект, но и его путь, поэтому вы можете вернуть объект с правильным контекстом.

person Martijn Pieters    schedule 02.09.2011
comment
Есть ли способ воссоздать такой контекст получения, используя только родные библиотеки zope? - person Alex M; 05.09.2011
comment
Да, путем повторной упаковки объекта; wrapped = child.__of__(parent) поместит дочерний элемент в контекст родителя, так что wrapped._aq_parent == parent. Хитрость заключается в том, как выяснить, кто является правильными родителями. См. также wiki.zope.org/zope2/Acquisition. - person Martijn Pieters; 06.09.2011

Насколько я знаю, правильный способ сделать это — использовать метод get экземпляра подключения:

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

РЕДАКТИРОВАТЬ: кажется, что dbroot._p_jar является объектом ZODB.Connection.Connection, как и возвращаемый тип db.open(), поэтому, возможно, можно предположить, что оба способа эквивалентны. Возможно, conn.get(...) кажется чище, поскольку не требует доступа к методам с префиксом подчеркивания.

person Erik Kaplun    schedule 01.08.2011
comment
В ZODB/utils.py есть oid_repr и repr_to_oid, которые полезны при работе с oids при отладке. - person Jean Jordaan; 06.08.2012