Updating add-on products for Plone 3.0
Note: Return to reference manual view.
1. General product development and migration tips for Plone 3.0
Depending on your product, it might be hard to include compatibility for both Plone 2.5 and Plone 3.0 in the same product. There are several reasons for this, but the main ones are:
- The workflow definition standard in CMF has changed
- The new portlet infrastructure (although it does support old-style portlets, performance will suffer)
- The introduction of viewlets as the main way to render content fragments in the layout
So, the general recommendation is:
- If your product is more complex than a simple type, create two releases — one for Plone 2.5 and one for Plone 3.0.
- If you used ArchGenXML to create your product, you should be able to regenerate your product from the UML model to get a Plone 3.0-compatible version.
Tip
- To further future-proof your product (for Plone 3.5 and 4.0), try the following:
- Start Zope in debug mode using
zopectl fgand use your product normally. Check if it outputs any deprecation warnings to the log window. - Disable the
plone_deprecatedskin layer and make sure your application still runs without it (this disables deprecated methods and deprecated CSS styles)
- Start Zope in debug mode using
Other recommendations and suggestions
- You can use the contentmigration product to write migrations for your own products. More information on this product can be found in the RichDocument tutorial
- A lot of the new components use Zope 3 views instead of templates. These can be customized through-the-web using the
portal_view_customizationstool. - Do not ever rely on the JS libraries in Plone being the same across releases. Use the KSS abstractions, the underlying implementation might (and will!) change.
These things are not mandatory yet, but represent best-practice recommendations that will save you from updating these parts in the future:
- QuickInstaller-based installation should use GenericSetup profiles instead
- use events instead of manage_ methods (which will probably disappear in plone 3.5 or 4.0)
- Packaging technology:
- Use python packages instead of Zope products
- Ship packages as eggs and register them with the Python Cheese Shop
- Use Python Paste to create new packages
- Suggestion: Use
ploneitorploneoutto create development and/or production environments that can easily be replicated
For more information about using the new python packages please refer to the Guide to Python packages reference guide.
2. CMFCore.permissions import syntax change
Typical error message when starting Zope:
File "Products/PloneHelpCenter/content/HelpCenter.py", line 29, in ?
from Products.CMFCore import CMFCorePermissions
ImportError: cannot import name CMFCorePermissions
What's causing it:
The following line is a common statement to get access to the permissions module, typically in the __init__.py file:
from Products.CMFCore import CMFCorePermissions
To make this work with both the new way of importing it and fall back to the old way if you're running an older version, replace the above with:
try: # New CMF
from Products.CMFCore import permissions as CMFCorePermissions
except ImportError: # Old CMF
from Products.CMFCore import CMFCorePermissions
Then you should be all set, and be able to support multiple versions with your product. Note that the try/except block is only necessary if you want to support Plone 2.1, if you're targeting Plone 2.5 and above, you only have to do the variant listed under "New CMF" in the example above.
To see a live example of this change, consult Poi changeset 40594.
3. Transaction module is no longer implicitly in Archetypes
Typical error message when starting Zope:
from Products.Archetypes import transaction ImportError: cannot import name transaction
Archetypes no longer imports transaction, so you will have to do it in your own module now, if you are using it. Change occurences of:
from Products.Archetypes import transaction
to:
import transaction
For a live example, see Poi changeset 40594.
4. get_transaction module rename
Typical error message:
NameError: global name 'get_transaction' is not defined
Just to show you a complete traceback of how this might look, here's the full thing as seen in a typical product install, where it is common to use subtransactions (for completeness and search engines):
2007-04-12 23:12:01 ERROR Zope.SiteErrorLog http://localhost:8080/nu/portal_quickinstaller/installProducts
Traceback (innermost last):
Module Products.CMFQuickInstallerTool.QuickInstallerTool, line 381, in installProduct
- __traceback_info__: ('Poi',)
Module Products.ExternalMethod.ExternalMethod, line 231, in __call__
- __traceback_info__: ((<PloneSite at /nu>,), {'reinstall': False}, (False,))
Module /Users/limi/Projects/Plone/3.0/Products/Poi/Extensions/Install.py, line 65, in install
NameError: global name 'get_transaction' is not defined
/Users/limi/Projects/Plone/3.0/Products/CMFQuickInstallerTool/QuickInstallerTool.py:409:
DeprecationWarning: This will be removed in ZODB 3.7:
subtransactions are deprecated; use sp.rollback() instead of transaction.abort(1),
where `sp` is the corresponding savepoint captured earlier
transaction.abort(sub=True)
To update this, replace:
get_transaction().commit(1)
with:
transaction.commit(1)
(keep the (1) part if it already exists in the code, omit it otherwise)
You might have to add an import transaction statement at the top of your file if you haven't imported it already.
For a live example, see the Install.py part of Poi changeset 40594.
5. ContentFactoryMetadata deprecation
Typical error message:
Error Type: exceptions.ImportError Error Value: cannot import name ContentFactoryMetadata
What causes this? Somewhere in your code, you have something like:
from Products.CMFCore.TypesTool import ContentFactoryMetadata
Update this to:
from Products.CMFCore.TypesTool import FactoryTypeInformation
instead, and you should be good to go. This change should work all the way back to Plone 2.1.
For a live example, see DataGridField changeset 7901.
6. Update your workflows to use GenericSetup profiles
Installing workflows via GenericSetup will make your product work only on Plone 2.5 and upwards, so make sure you create a special release/branch if you want your product to still work on Plone 2.1/2.0 (which are unsupported releases when Plone 3.0 is released).
Typical error message that indicates that you are trying to install workflows not using GenericSetup:
ImportError: cannot import name addWorkflowFactory
For existing workflows, the easiest way to make the product install use GenericSetup for workflows is:
- Install your product (and its workflows) using Plone 2.5.
- Using the
portal_setuptool in the ZMI, export a snapshot of the current site profile:- Click the
Exporttab. - Select the parts you want to export the configuration for (in this case,
Workflow Tool). - Click the
Export Selected Stepsbutton. - You will now get a tar file named something like
setup_tool-20070424225827.tar.
- Click the
- Unpack the tar file, and put the resulting files and directories in a directory
profiles/default/in the root of your product. - Remove the workflow directories in
workflow/that are not part of your product, and editworkflows.xmlso that it only has the information for your workflows. See Poi changeset 41071 for an example. - Delete your old '.py'-based workflow definitions in
Extensions, but make sure you keep any workflow scripts, since these will be referenced from the profile definitions. - Add a
configure.zcmlfile in the root of your product that registers the default profile. See Poi's configure.zcml for an example. - Remove the redundant code from
Extensions/Install.pyand add the boilerplate code to invoke the GS setup, see Poi changeset 41071 for an example.
This process is also the same for any code you want to move to GenericSetup, in the Poi example, we also moved the catalog metadata and various other things to use GenericSetup profiles, and could get rid of most of Install.py in the process.
7. Searching users/groups via the Membership tool is deprecated
XXX Need examples of this. (Wichert)
8. Portlets have a new infrastructure
Portlets have been re-implemented using the Zope 3 component architecture. Change custom portlets to use plone.app.portlets if possible.
Old portlets are supported via a fallback mechanism called Classic Portlet; the portlet management screen has functionality for doing inline migration for old portlets. Note that using the old portlets mechanism will affect your site performance negatively.
XXX needs examples. (Martin?)
9. main_template now uses Zope 3 viewlets
If have previously shipped customized versions of templates like header.pt, viewThreadsAtBottom.pt or global_contentmenu.pt to get things into the page, please switch to viewlets instead, as it makes it much easier for multiple products to co-exist without stepping on each others changes.
Documentation and examples can be found in this tutorial.
10. Plone 3 does not create member folders by default
While this was always considered bad practice, it's now official. Don't do it. :)
11. Plone Tableless theme no longer exists
For those of you who desire a tableless implementation of the default skin, please backport the markup changes to the new main_template.
NuPlone (the new theme in Plone 3.0) is a table-less alternative that we hope you like.
12. Document Actions now use Zope 3 viewlets
The new approach uses viewlets, and its default position has also been moved to the bottom of the page. It also defaults to a text-based representation instead of the icons that it was using earlier, since document actions are often too abstract to create good icons for.
13. Products installing workflows may need to add permissions
The new "Editor" (aka. "Can Edit" on the Sharing page) in Plone 3.0 makes it easy to let people collaborate on content authoring. In some cases, editing also means the ability to add new objects inside the object people are editing.
For this to work, third party content types that add custom workflows will have to either use one of the standard "add content" permissions or explicitly give Editor the Add portal content role.
See Ticket #6265 for the changeset and full explanation.
14. Indexes declared in Archetypes schemata need to be moved to GenericSetup
This applies if you have moved from using install_types() in Extensions/Install.py, to installing new content types/FTIs with GenericSetup using a types.xml import step.
For each field that specifies an index, like this example from PoiIssue.py r40594
:
StringField(
name='issueType',
index="FieldIndex:schema",
widget=SelectionWidget(
label="Issue type",
description="Select the type of issue.",
label_msgid='Poi_label_issueType',
description_msgid='Poi_help_issueType',
i18n_domain='Poi',
),
enforceVocabulary=True,
vocabulary='getIssueTypesVocab',
required=True
),
…you need to move the creation to catalog.xml with GenericSetup. If there is index="FieldIndex", that means you need a new index, of type FieldIndex, with the name being the name of the accessor method:
<index name="getIssueType" meta_type="FieldIndex">
<indexed_attr value="getIssueType"/>
</index>
If there is also :schema or :metadata, e.g. index="FieldIndex:schema", you also need a metadata column:
<column value="getIssueType"/>
This is necessary because the schema does not really exist at install time, so there is no way GenericSetup can inspect it and configure new indexes. This was a bad design from the start, as portal-wide indexes do not belong in type-specific schemata anyway.
15. The "Sharing" tab is now a global action
The "Sharing" tab now points to the @@sharing view, and is defined as a global action in the object category. If you have a custom content type and you have set up the local_roles action, which would normally be pointing to the folder_localrole_from template, you should remove it. It will be removed from existing, installed types during migration.
If you do not remove the action, the user will see two "Sharing" tabs.
For an example of the canonical set of actions and aliases, see the GenericSetup definition of the Document FTI. Of course, you may not need the References, History or External Edit actions in your own types.
16. Multi page schemas
In Plone 3.0, all fields from all schematas will be loaded at once. If you depend on your schematas (fieldsets) to be processed one page after the other, you'll need to mark your Archetypes content type that uses it (not the schema itself) with the IMultiPageSchema interface.
The interface lives in Products.Archetypes.interfaces.IMultiPageSchema. The code to mark your content type would look like this:
from zope import interface from Products.Archetypes.interfaces import IMultiPageSchema # ... interface.alsoProvides(MyContentType, IMultiPageSchema)
17. Enable inline editing (aka. QuickEdit)
Adding inline editing and validation support to your view templates is as easy as calling the Archetypes widgets in view mode.
As an example, consider the following typical code from Plone 2.5:
<h1 tal:content="here/getSomeVariable" class="documentFirstHeading">
Variable goes here
</h1>
Now, to render the same thing, with an h1 tag and a class on it, you do:
<h1 class="documentFirstHeading">
<metal:field use-macro="python:here.widget('someVariable', mode='view')">
Variable goes here
</metal:field>
</h1>
This will keep whatever tags and styling you want around the item, and render the inline editing inside of it. It's also backwards compatible with earlier Plone versions — although these don't get the inline editing, obviously.