Content Identification (ids)¶
Description
Different ids, UIDs, integer ids or whatever can identify your Plone content and give access to it.
Introduction¶
Id¶
Content id generally refers the item id within the folder.
Together with folder path this identifies the content in unique way.
Naturally, this id changes when the content is renamed or moved.
Use traversing to resolve object by path+id.
UID and UUID¶
UID is a unique, non-human-readable identifier for a content object which stays on the object even if the object is moved.
Plone uses UUIDs for
Storing content-to-content references (Archetypes, ReferenceField)
Linking by UIDs - this enables persistent links even though the object is moved
Plain UID is supported by Archetypes only and is based on reference_catalog
UUID is supported by Archetypes and Dexterity both and you should use this for new projects
UIDs are available for Archetypes content and unified UUIDs for both Archetypes and Dexterity content items since plone.app.dexterity
version 1.1.
Note
If you have pre-Dexterity 1.1 content items you must run a migration step in portal_setup to give them UUIDs.
To get object UUID you can use plone.app.uuid package.
Getting object UUID:
from plone.uuid.interfaces import IUUID
# BrowserView helper method
def getUID(self):
""" AT and Dexterity compatible way to extract UID from a content item """
# Make sure we don't get UID from parent folder accidentally
context = self.context.aq_base
# Returns UID of the context or None if not available
# Note that UID is always available for all Dexterity 1.1+
# content and this only can fail if the content is old not migrated
uuid = IUUID(context, None)
return uuid
Looking up object by UUID:
Use plone.app.uuid.utils.uuidToObject:
from plone.app.uuid.utils import uuidToObject
...
obj = uuidToObject(uuid)
if not obj:
# Could not find object
raise RuntimeError(u"Could not look-up UUID:", uuid)
More info:
UUID Acquisition Problem With Dexterity Content Types¶
Make sure your Dexterity content type has the plone.app.referenceablebehavior.interfaces.IReferenceable behavior enabled.
If not, when querying for an object’s UUID, you will get its parent UUID.
Then you can end up with a lot of objects with the same UUID as their parent.
If you run into this issue, here’s an easy upgrade step to fix it:
import transaction
from plone.uuid.handlers import addAttributeUUID
from Products.CMFCore.utils import getToolByName
...
def recalculate_uuids(setup_tool):
# Re-import types definition, so IReferenceable is enabled.
setup_tool.runImportStepFromProfile(
"profile-my.package:default",
'typeinfo')
catalog = getToolByName(setup_tool, 'portal_catalog')
for index, brain in enumerate(catalog(portal_type="my.custom.content.type")):
obj = brain.getObject()
if not getattr(obj, '_plone.uuid', None) is None:
# If an UUID has already been calculated for this object, remove it
delattr(obj, '_plone.uuid')
# Recalculate object's UUID
addAttributeUUID(obj, None)
obj.reindexObject(idxs=['UID'])
if index % 100 == 0:
# Commit every 100 items
transaction.commit()
# Commit at the end
transaction.commit()
Make sure to have the IReferenceable behavior listed in the content type XML definition before running the upgrade step.
Note
This upgrade step will recalculate the UUID for all “my.custom.content.type” objects.
intids¶
Integer ids (“intids”) are fast look-up ids provided by plone.app.intid
and five.intid
packages.
Instead of relying on globally unique identifier strings (UIDs) they use 64-bit integers, making low-level resolution faster.