Creating objects

Creating content objects

Use invokeFactory(portal_type, id). invokeFactory() is available on all folderish content objects.

Example (from unit tests):

self.loginAsPortalOwner()
self.portal.invokeFactory("Folder", "folder")
self.portal.folder.invokeFactory("Folder", "subfolder")
self.portal.folder.subfolder.invokeFactory("Document", "doc")

Restricting available types per folder

Plone can restrict available content types which you can create in folder through Add... menu.

Restricting available types per content type

portal_types defines which content can be created inside which content type. This is allowed_content_types setting and you can change it through ZMI as well.

You can set the restriction in GenericSetup profiles/default/types/YourType.xml:

<property name="filter_content_types">True</property>

<property name="allowed_content_types">
        <element value="YourContentTypeName" />
        <element value="Image" />
        <element value="News Item" />
        ...
</property>

Restricting available types per folder instance

In UI, you can access this feature through Add... menu Restrict option.

Type contraining is managed by ATContentTypes product

Example:

# Set allowed content types
from Products.ATContentTypes.lib import constraintypes

# Enable contstraining
folder.setConstrainTypesMode(constraintypes.ENABLED)

# Types for which we perform Unauthorized check
folder.setLocallyAllowedTypes(["ExperienceEducator"])

# Add new... menu  listing
folder.setImmediatelyAddableTypes(["ExperienceEducator"])

You can also override contraintypes accessor method to have programmable logic which types are addable and which not.

More info

Creating OFS objects

Zope has facilities for basic folder and contained objects by OFS subsystem. You do not need to work with raw objects unless you are doing your custom lightweight, Plone free, persistent data.

More examples in

Archetypes object construction

The following applies to Archetypes based objects only.

Archetypes content contruction has two phases

  1. Object is created using ?createType= URL or Folder.invokeFactory() call. If createType is used then the object is given a temporary id. Object has a “in creationg” flag set.
  2. Object is saved for the first time and the final id is generated based on the object title. Object id is renamed. Creation flag is cleared.

You are supposed to call either object.unmarkCreationFlag() or object.processForm() after content is created manually using invokeFactory().

processForm() will perform following tasks:

  • unmarks creation flag
  • renames object according to title
  • reindexes object
  • invokes after_creation script and fires ObjectInitialzed event

If you don’t want to do particular step, look to Archetypes/BaseObject.py and call only what you really want. But unless unmarkCreationFlag() is called the object will behave strangely after the first edit.

Factory type information

Factory type information (FTI) is responsible for content creation in the portal. It is independend from content type (Archetypes, Dexteriry) subsystems.

Warning

FTI codebase is historical (updated circa 2001). Useful documentation might be hard to find.

FTI is responsible for

  • Which function is called when new content type is added
  • Icons available for content types
  • Creation views for content types
  • Permission and security
  • Whether discussion is enabled
  • factory_type_information is a dictionary that is used elsewhere in the code (often in __init__.py of a product) to set the initial values for a ZODB Factory Type Information object (an object in the portal_types tool)

See

Content does not show in Add Menu or Unauthorized errors

When creating new content types, many factors can silently fail due to human errors in the complex content type setup chain and security limitations. The effect is that you don’t see your content type in Add drop down menu. Here are tips for debugging.

  • Is your product broken due to Python import time errors? Check Zope Management Interface -> Control panel -> Products. Turn on Zope debugging mode to trace import errors.
  • Have you rerun the quick installer (GenericSetup) after creating/modifying the content type?
  • Do you have a correct Add permission for the product? Check __init__.py ContentInit() call.
  • Does it show up in the portal factory? Check ZMI -> portal_factory and factorytool.xml.
  • Is it corretly registered as a portal type and implictly addable? Check ZMI -> portal_types. Check default/profiles/type/yourtype.xml
  • Does it have correct product name defined? Check ZMI -> portal_types.
  • Does it have a proper factory method? Check ZMI -> types_tool. Check Zope logs for _queryFactory and import errors.
  • Does it register itself with Archetypes? Check ZMI -> archetypes_tool. Make sure that you have ContentInit properly run in your __init__.py. Make sure that all modules having Archetypes content types defined and registerType() call are imported in __init__py.

Populating folder on creation

Archetypes have a hook called initializeArchetype(). Your content type subclass can override this.

Example:

class LandingPage(folder.ATFolder):
    """Landing page"""

    def initializeArchetype(self, **kwargs):
        """
        Prepopulate folder during the creation.

        Create five subfolders of "BigBlock" type, with title and id preset.
        """
        folder.ATFolder.initializeArchetype(self, **kwargs)

        for i in range(0, 5):
            id = "container" + str(i)
            self.invokeFactory("BigBlock", id, title="Big block " + str(i+1))
            item = self[id]

            # Clear creation flag so that edit screen
            item.markCreationFlag()