Description
Plone’s content type subsystems and creating new content types programmatically.
Plone has two kind of content types subsystems
Flexible architecture allows other kinds of content type subsystems as well.
Plone maintains available content types in portal_types tool.
portal_types is a folderish content where type information are child objects, keyed by portal_type metadata.
portal_factory is a tool responsible for creating the persistent object representing the content.
Below is an example Zope 3 vocabulary factory which will return all the available content types to be used with multi-selection field.
Define vocabulary in ZCML:
<utility
provides="zope.schema.interfaces.IVocabularyFactory"
component=".vocabularies.content_types_vocabulary"
name="mfabrik.like.content_types"
/>
Then have the factory code for it in vocabularies.py:
"""
Zope 3 schema vocabulary factory for making multiple choices between installed content types of Plone site.
http://mfabrik.com
"""
__license__ = "GPL 2"
__copyright__ = "2010 mFabrik Research Oy"
__author__ = "Mikko Ohtamaa <mikko@mfabrik.com>"
__docformat__ = "epytext"
from Acquisition import aq_inner
from zope.app.component.hooks import getSite
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
from Products.CMFCore.utils import getToolByName
def make_terms(items):
""" Create zope.schema terms for vocab from tuples,
@return: Generator of SimpleTerm objects
"""
terms = [ SimpleTerm(value=pair[0], token=pair[0], title=pair[1]) for pair in items ]
return terms
def friendly_types(site):
""" List user selectable content types.
Note that there exist a method in IPortalState utility view for this, but we cannot
use it, because vocabulary factory must be available in contexts where there is
no HTTP request (e.g. installing add-on product).
This code is copy-pasted from https://svn.plone.org/svn/plone/plone.app.layout/trunk/plone/app/layout/globals/portal.py
@return: Generator for (id, type_info title) tuples
"""
context = aq_inner(site)
site_properties = getToolByName(context, "portal_properties").site_properties
not_searched = site_properties.getProperty('types_not_searched', [])
portal_types = getToolByName(context, "portal_types")
types = portal_types.listContentTypes()
# Get list of content type ids which are not filtered out
prepared_types = [t for t in types if t not in not_searched]
# Return (id, title) pairs
return [ (id, portal_types[id].title) for id in prepared_types ]
def content_types_vocabulary(context):
"""
A vocabulary factory for making a choice of a portal type.
@param context: Assume Plone site.
@return: SimpleVocabulary containing (portal type id, portal type title) pairs.
"""
# This special case must be handled by plone.app.registry quick installing registry.xml
# which refers to zope.schema refering to this vocabulary
# site information is *not* available
try:
import plone.registry.record
import plone.registry.recordsproxy
if isinstance(context, plone.registry.record.Record) or isinstance(context, plone.registry.recordsproxy.RecordsProxy):
context = getSite()
except ImportError:
pass
items = friendly_types(context)
return SimpleVocabulary(make_terms(items))
This instructions apply for Archetypes subsystem based content types
Related how tos
ノート
Creating types by hand is not worth of the problems. Please use a code generator to create the skeleton for your new content type.
警告
Content type name must not contain spaces. Content type name or description must not contain non-ASCII letters. If you need to change these please create a translation catalog which will translate the text to one with spaces or international letters.
Creating types by hand is not worth of the problems.
Implictly allowed is flag whether the content is globally addable or must be specifically enabled for certain folders.
The following example allows creation of Large Plone Folder anywhere at the site (it is disabled by default). For available properties, see TypesTool._advanced_properties.
Example:
portal_types = self.context.portal_types
lpf = portal_types["Large Plone Folder"]
lpf.global_allow = True # This is "Globally allowed" property