复制后重命名 Dexterity 对象 (id)
Rename Dexterity object (id) after copy
使用 INameChooser
在创建时选择对象 ID 很简单。
但我们也希望能够在克隆后选择对象 ID(并避免在对象 ID 中使用 copy_of
)。
我们尝试了几种不同的解决方案:
- 活动订阅者:
OFS.interfaces.IObjectClonedEvent
zope.lifecycleevent.interfaces.IObjectAddedEvent
- ...
manage_afterClone
内容方法 class
每次,我们都会收到回溯,因为我们“过早”更改了 ID。例如当使用 Plone API :
File "/Users/laurent/.buildout/eggs/plone.api-2.0.0a1-py3.7.egg/plone/api/content.py", line 256, in copy
return target[new_id]
File "/Users/laurent/.buildout/eggs/plone.folder-3.0.3-py3.7.egg/plone/folder/ordered.py", line 241, in __getitem__
raise KeyError(key)
KeyError: 'copy_of_87c7f9b7e7924d039b832d3796e7b5a3'
或者,在 Plone 实例中使用复制/粘贴:
Module plone.app.content.browser.contents.paste, line 42, in __call__
Module OFS.CopySupport, line 317, in manage_pasteObjects
Module OFS.CopySupport, line 229, in _pasteObjects
Module plone.folder.ordered, line 73, in _getOb
AttributeError: 'copy_of_a7ed3d678f2643bc990309cde61a6bc5'
这是合乎逻辑的,因为 ID 在事件通知/manage_afterClone
调用之前存储以备后用。
即使在容器上定义 _get_id
也无法定义 ID,因为我们没有从中获取属性(并生成 ID)的对象。
但是,我们怎样才能以干净的方式实现这一目标呢?
请告诉我有比重新定义 _pasteObjects
(OFS.CopySupport
) !
更好的解决方案
感谢您的意见!
很遗憾不是...
但是您可以从 _get_id
.
中访问原始对象
例如:
from OFS.CopySupport import _cb_decode
from plone import api
...
def _get_id(self, id_):
# copy_or_move => 0 means copy, 1 means move
copy_or_move, path_segments = _cb_decode(self.REQUEST['__cp']
source_path = '/'.join(path_segments[0]) # Imlement for loop for more than one copied obj.
app = self.getPhysicalRoot()
# access to source obj
source_obj = app.restrictedTraverse(source_path)
# Do whatever you need - probably using INameChooser
....
为了有一个规范的修补方法,我使用 collective.monkeypatcher
安装后在 ZCML 中添加以下内容:
<include package="collective.monkeypatcher" />
<monkey:patch
class="OFS.CopySupport.CopyContainer"
original="_get_id"
replacement="patches.patched_get_id"
/>
其中 patches.py
是包含新方法 patched_get_id
的模块,它取代了 _get_id
.
很抱歉,我没有更好的消息告诉您,但这就是我解决类似需求的方法。
此代码 (patched _get_id
) 在 id 的末尾添加一个计数器(如果已经存在的话)。
def patched_get_id(self, id_)
match = re.match('^(.*)-([\d]+)$', id_)
if match:
id_ = match.group(1)
number = int(match.group(2))
else:
number = 1
new_id = id_
while new_id in self.objectIds():
new_id = '{}-{}'.format(id_, number)
number += 1
return new_id
使用 INameChooser
在创建时选择对象 ID 很简单。
但我们也希望能够在克隆后选择对象 ID(并避免在对象 ID 中使用 copy_of
)。
我们尝试了几种不同的解决方案:
- 活动订阅者:
OFS.interfaces.IObjectClonedEvent
zope.lifecycleevent.interfaces.IObjectAddedEvent
- ...
manage_afterClone
内容方法 class
每次,我们都会收到回溯,因为我们“过早”更改了 ID。例如当使用 Plone API :
File "/Users/laurent/.buildout/eggs/plone.api-2.0.0a1-py3.7.egg/plone/api/content.py", line 256, in copy
return target[new_id]
File "/Users/laurent/.buildout/eggs/plone.folder-3.0.3-py3.7.egg/plone/folder/ordered.py", line 241, in __getitem__
raise KeyError(key)
KeyError: 'copy_of_87c7f9b7e7924d039b832d3796e7b5a3'
或者,在 Plone 实例中使用复制/粘贴:
Module plone.app.content.browser.contents.paste, line 42, in __call__
Module OFS.CopySupport, line 317, in manage_pasteObjects
Module OFS.CopySupport, line 229, in _pasteObjects
Module plone.folder.ordered, line 73, in _getOb
AttributeError: 'copy_of_a7ed3d678f2643bc990309cde61a6bc5'
这是合乎逻辑的,因为 ID 在事件通知/manage_afterClone
调用之前存储以备后用。
即使在容器上定义 _get_id
也无法定义 ID,因为我们没有从中获取属性(并生成 ID)的对象。
但是,我们怎样才能以干净的方式实现这一目标呢?
请告诉我有比重新定义 _pasteObjects
(OFS.CopySupport
) !
感谢您的意见!
很遗憾不是...
但是您可以从 _get_id
.
例如:
from OFS.CopySupport import _cb_decode
from plone import api
...
def _get_id(self, id_):
# copy_or_move => 0 means copy, 1 means move
copy_or_move, path_segments = _cb_decode(self.REQUEST['__cp']
source_path = '/'.join(path_segments[0]) # Imlement for loop for more than one copied obj.
app = self.getPhysicalRoot()
# access to source obj
source_obj = app.restrictedTraverse(source_path)
# Do whatever you need - probably using INameChooser
....
为了有一个规范的修补方法,我使用 collective.monkeypatcher
安装后在 ZCML 中添加以下内容:
<include package="collective.monkeypatcher" />
<monkey:patch
class="OFS.CopySupport.CopyContainer"
original="_get_id"
replacement="patches.patched_get_id"
/>
其中 patches.py
是包含新方法 patched_get_id
的模块,它取代了 _get_id
.
很抱歉,我没有更好的消息告诉您,但这就是我解决类似需求的方法。
此代码 (patched _get_id
) 在 id 的末尾添加一个计数器(如果已经存在的话)。
def patched_get_id(self, id_)
match = re.match('^(.*)-([\d]+)$', id_)
if match:
id_ = match.group(1)
number = int(match.group(2))
else:
number = 1
new_id = id_
while new_id in self.objectIds():
new_id = '{}-{}'.format(id_, number)
number += 1
return new_id