Rename Dexterity object (id) after copy

It's simple to choose the object ID at creation time with INameChooser.
But we also want to be able to choose the object ID after a clone (and avoid copy_of in object ID).

We tried several different solutions :

  • subscribers on events :
    • OFS.interfaces.IObjectClonedEvent
    • zope.lifecycleevent.interfaces.IObjectAddedEvent
    • ...
  • manage_afterClone method on content class

Every time, we get a traceback because we changed the ID "too soon". For example when using 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'

Or, with a Copy / Paste in the Plone instance :

  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'

It's logical, because the ID is stored before events notification / manage_afterClone call for later use.

Even defining a _get_id on containers cannot work to define the ID, because we don't have the object to get attributes from (and generate the ID).

But then, how could we achieve this in a clean way ?
Please tell me there is a better solution than redefining _pasteObjects (OFS.CopySupport) !

Thank you for your inputs !

Did you try creating a custom content rule on adding content? Or using the same subscribers the content rules use on adding?

Thank your very much for your answer @yurj, but I tried it and got the same traceback with the content rule as with a Copy / Paste in the Plone instance :frowning:

1 Like

There's a IObjectCopiedEvent event somewhere. You can rename the object after the fact.

I don't know what code actually determines that copy_of_ prefix, but you can check for that in the event handler.

It is Zope itself, CopySupport.py.

An alternative is a monkeypatch, it is a very small method. But IObjectCopiedEvent would be perfect.

https://docs.plone.org/develop/addons/components/events.html#copy-events

zope.lifecycleevent.IObjectCopiedEvent

    is triggered when an object is copied (will also fire IObjectCreatedEvent event code).

Also tried that, but with IObjectCopiedEvent event, we do not seem to have the new object container (object is not in its acquisition chain). The container is needed for rename, either via plone.api or "by hand" with manage_renameObject.

Thanks !