Recomended way for setting ID

Hey,

what is the recommended way to set the ID of a newly created item? I want to create a dexterity content item in a folder. I need an incremental number as ID. "1" for the first item in a folder, "2" for the second, etc.

When there is no behavior (INameFromTitle) set, I'll get content-type-1, content-type-2, etc.

I've tried a behavior:

@implementer(INameFromTitle)
@adapter(INameGenerator)
class NameGenerator(object):

    def __init__(self, context):
        self.portal_type = getattr(
            aq_base(context), 'portal_type', None).title()

    @property
    def title(self):
        custom_id = NameGenerator.generate_id(self.portal_type)
        return custom_id

    @staticmethod
    def generate_id(portal_type):
        brains = api.content.find(
            portal_type = portal_type,
            sort_on = 'id',
            sort_order = 'descending',
        )
        if brains:
            new_id = int(brains[0].id) + 1
            return str(new_id)
        return '1'

Registered with

  <plone:behavior
      name="foo.bar.behaviors.INameGenerator"
      title="Custom ID Generation"
      description="Automatically generate incremenetal ID"
      provides="foo.bar.interfaces.INameGenerator"
      for="plone.dexterity.interfaces.IDexterityContent"
      />

  <adapter factory=".behaviors.NameGenerator" />

This basically works. Since I don't have the container (right?), I can only check via catalog per Plone Site. This example is not working for items created via post install in setuphandlers. There are somehow issues with the catalog...

I've also tried a event (IObjectCreatedEvent) but this feels somehow ugly.

Any ideas or e.g. already working similar code somewhere in the Plone universe?

Cheers
Stefan

I've implemented custom id generation slightly different. Instead of a behavior I implemented a simple adapter, from IMyContentType to INameFromTitle:

@implementer(INameFromTitle)
@adapter(IMyContentType)
class NameFromTitle(object):
    u"""Adapter from `IMyContentType` to `INameFromTitle`.

    This adapter will provide the `title` that will be used by an `INameChooser` as input to
    generate the ID.
    """

    def __init__(self, context):
        self.context = context

    @property
    def title(self):
        return 'my_custom_title_to_be_converted_to_an_id'

In configure.zcml:

  <adapter factory=".content.mycontenttype.NameFromTitle" />

And make sure "My Content Type" does not have the default INameFromTitle behavior enabled.

Yes, I tested and the container is not available at this moment. Perhaps you could use IObjectAddedEvent to rename the item after creation, using plone.api.rename. Not very elegant indeed.

I was bitten by a bug when creating the items programatically, perhaps this is your case too:

Plone Foundation Code of Conduct