Rename by Title

Plone derives the id of a content object from its title only once — when the object is created. Renaming the object later is a separate, manual step.

The Rename by title behavior removes that step: whenever the title of a content object changes, its id (and therefore its URL) is regenerated from the new title.

Behavior

When the behavior is active on a content type:

  • Editing the title through the REST API or the classic edit form renames the object. Editing any other field leaves the id untouched.

  • The new id is normalized the same way Plone normalizes ids on creation, honouring the editor’s preferred language (A brand new titlea-brand-new-title).

  • If a sibling already occupies the normalized id, a numbered suffix is appended (taken-title-1). That suffixed id then stays stable — further edits of the same title do not count the number up.

  • The rename runs with elevated privileges, so an editor who may modify the content but not delete it in its parent folder can still trigger it.

  • Old URLs keep working: the rename registers a redirect, and requests to the previous URL answer with a redirect to the new one.

  • Renaming re-validates the container constraints. If the object’s type is not addable in its parent — content created programmatically past the constraints, or a constraint tightened afterwards — the rename is skipped and logged as a warning. The edit itself still goes through.

It does not matter whether title comes from a behavior such as plone.basic or from a field declared in the type’s own supermodel XML schema.

Staging

Working copies are never renamed — their id belongs to the staging mechanism, not to the title. When a working copy is applied, the title is written back to the baseline and the baseline is renamed instead.

REST API

Nothing needs to be sent explicitly; the rename is a side effect of changing the title.

await fetch('/Plone/original-title', {
    method: 'PATCH',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ title: 'A brand new title' }),
});

// The content now lives at /Plone/a-brand-new-title
const response = await fetch('/Plone/a-brand-new-title', {
    headers: { 'Accept': 'application/json' },
});

Requests to the old path are redirected:

import requests

response = requests.get(
    'http://localhost:8080/Plone/original-title',
    headers={'Accept': 'application/json'},
)
print(response.json()['id'])  # a-brand-new-title

Clients that cache content URLs should follow redirects, or re-read the @id from the response after a title change.

Configuration

The behavior is opt-in. To activate it on a content type, add wcs.backend.content.behaviors.auto_rename.IAutoRename to the FTI’s behaviors list via GenericSetup:

<object name="MyContentType" meta_type="Dexterity FTI">
  <property name="behaviors" purge="false">
    <element value="wcs.backend.content.behaviors.auto_rename.IAutoRename"/>
  </property>
</object>

Enabling it on an existing site needs an upgrade step importing that profile. Existing objects are not renamed retroactively — their id follows as soon as their title is edited the next time.