Creating a new content type 1-2-3
This applies for Plone 2.1.x and still works in Plone 2.5.x. It is encouraged to use newer mechanisms provided by Five subsystem when you start new products from scracth. Please read Martin Aspeli's excellent tutorial about the subject.
Archetypes is a Plone subsystem to define new content types. Content types are Python classes which have special attributes described by Archetypes product. The most import of them is schema which defines what fields your content type has. Archetypes reference manual is handy.
File system product skeleton
You need a file system product where new content types is added. You can take the existing product and rip its flesh away or use examples provided by Archetypes manual.
Content type Python module
Create a Python module containing your content type class declaration
- Create a .py module to the "content" folder of the product.
- Add Necessary dependency imports for fields, widgets, parent schema and parent class
Example
# Plone imports from Products.Archetypes.public import * from Products.ATContentTypes.content.base import ATCTContent from Products.ATContentTypes.content.base import updateActions, updateAliases from Products.ATContentTypes.content.schemata import ATContentTypeSchema from Products.ATContentTypes.content.schemata import finalizeATCTSchema # Local imports from Products.MyCustom.BulletField import BulletField from Products.MyCustom.BulletWidget import BulletWidget from Products.MyCustom.config import *
- Create the schema definition for your content type. See Archetypes manual for available fields, widgets and their properties.
Example
schema=ATFolderSchema.copy() + Schema((
TextField('isItForMe',
default='',
searchable=True,
widget=RichWidget(
label='Is it for me?',
)
),
TextField('benefits',
default='',
searchable=True,
widget=RichWidget(
label='What are the benefits of taking this course?',
)
),
LinksField('whatDoILearn',
default='',
searchable=True,
widget=RichWidget(label='What do I learn?', macro="what_do_i_learn_widget.pt")
),
))
finalizeATCTSchema(schema)
The class definition defines security and general properties of your content type.
Example:
class CoursePage(ATFolder):
""" Courses page content type
"""
# Internal programming id which Plone uses to refer this type
portal_type = meta_type = 'CoursePage'
# User readable name in "Add new content" drop down menu
archetype_name = 'Course page'
# Help text for Add new content drop down menu
typeDescription = "A course description telling what students should expect for this course"
# Fields used in this content type (as defined above)
schema = schema
# If true, this content type can be created anywhere at the site
global_allow = True
# We limit what kind of items are allowed in this folderish content type
filter_content_types = True
# List of allowed content types
allowed_content_types = [ "GeneralLSMPage", "CourseModulePage", "CourseModePage", "GeneralLSMPage2", "CourseFeesModePage" ]
You need to use registerType to register your class definition for Zope security manager.
# CoursePage is your Python class # PROJECTNAME is the name of your product and it's usually declared in config.py registerType(CoursePage, PROJECTNAME)
Initializing the product
To make your content type available for Plone
- You need to import it during the Plone start-up sequence
- You need to run the quick installer script to create persistent portal_type entries for your content type
In __init__.py of your product, import the new content type module so that Zope security manager is initialized for it
"""
Copyright 2006 xxx
"""
__author__ = 'Mikko Ohtamaa <mikko@redinnovation.com>'
__docformat__ = 'epytext'
from Products.Archetypes.public import process_types, listTypes
from Products.Archetypes.ArchetypeTool import getType
from Products.CMFCore.DirectoryView import registerDirectory
from Products.CMFCore import utils as CMFCoreUtils
from config import *
from Permissions import *
def initialize(context):
""" Registers all classes to Zope
@param context Zope/App/ProductContext instance
"""
# initialize security context
from content import MyCustomContentTypeModule
# Register our skins directory - this makes it available via portal_skins.
registerDirectory(SKINS_DIR, GLOBALS)
# helper function to go through all content types in your product
content_types, constructors, ftis = process_types(
listTypes(PROJECTNAME),
PROJECTNAME)
# Initialize content types
CMFCoreUtils.ContentInit(
PROJECTNAME + ' Content',
content_types = content_types,
permission = PermissionNameToCreateThisContent,
extra_constructors = constructors,
fti = ftis,
).initialize(context)
Then, you need to remember to register types in Extension/Install.py quick installer script. This creates persistent portal_type entries for your content type. Each time you change the general properties of your content type (everything except schema) you need to rerun the quick installer.
"""
Extension/Install.py quick installer script
Your Copyright line here
"""
__author__ = 'Mikko Ohtamaa <mikko@redinnovation.com>'
__docformat__ = 'epytext'
# Python imports
from cStringIO import StringIO
# Plone imports
from Products.Archetypes.public import listTypes
from Products.Archetypes.Extensions.utils import installTypes, install_subskin
# Local imports
from Products.MyProduct.Extensions.utils import *
from Products.MyProduct.config import *
def install(self):
""" This is called by Plone quick installer tool
@param self portal instance object
@return String which is added for the installer log
"""
out = StringIO()
# Register layout files in the portal
install_subskin(self, out, GLOBALS)
registerStylesheets(self, out, STYLESHEETS)
registerScripts(self, out, JAVASCRIPTS)
# Register Archetypes types in the portal
installTypes(self, out, listTypes(PROJECTNAME), PROJECTNAME)
print >> out, "Installation completed."
return out.getvalue()
def uninstall(self):
# TODO
out = StringIO()