I need to restrict the creation of a custom (Dexterity) content type to only one instance (per site). How? It should be trivial...
Add an event subscriber for zope.lifecycleevent.interfaces.IObjectAddedEvent
that would implement such a check e.g. by performing a catalog search. Raise an exception in case ...
Disclaimer: exceptions from event handlers are possibly swallowed somewhere in Plone
https://docs.plone.org/external/plone.app.dexterity/docs/advanced/event-handlers.html
And there is also some "magic" in Zope/OFS/ObjectManager ... setting __replaceable__ = UNIQUE
on an object may help, perhaps.
I had a similar requirement which had some edge cases: do test the validator that the catalog search is not finding the singleton item you just created and therefore blocks.
(Or for example when moving the Item, which would trigger a new ObjectAddedEvent.)
Try and see if disabling "Implicitly allowed" (or global allow, or something) for the content type is good enough.
This can be set in the ( /@@content-controlpanel ) control panel
Replying to myself:
I added a init to the content type class and used portal_catalog to check the number of indexed objects of that type. Something like:
from plone import api
from plone. dexterity.content import Item
class MyItem(Item):
def __init__(self, id=None, **kwargs):
catalog = api.portal.get_tool('portal_catalog')
brains = catalog(portal_type='mytype')
if brains:
raise Exception('Only one "mytype" object is allowed per Plone instance')
super(MyItem, self).__init__(id, **kwargs)
Thanks to all.