Upgrading Plone 5.2 to 6.0#
Plone 6.0 has seen the following major changes. Some may require changes in your setup.
Removed portal_quickinstaller
#
Plone no longer ships with the portal_quickinstaller
tool (CMFQuickInstallerTool
).
In existing sites, the standard upgrade will remove the tool.
This is the final step in a deprecation path that started in Plone 5.1.
Documentation of how to switch to GenericSetup
and the new installer, can be seen in Upgrade a custom add-on to Plone 5.1.
See also
Dexterity site root#
For content types, in Plone 4 and 5 you had the option to use the old Archetypes or the new Dexterity framework. The Plone site root object was neither: it was in its own class. In Plone 6, the site root itself is a Dexterity object.
When you upgrade a site from Plone 5.2 to 6.0, at first you will see an empty site root.
Do not panic.
😱
Your content is only temporarily invisible.
Perform the standard migration via the @@plone-upgrade
view, and your content will be visible again.
See also
Volto#
Plone 6 ships with a new React-based frontend, Volto.
When you use the Plone
package in your project, you will get the plone.volto
integration package.
This package prepares your Plone site's backend as a REST API.
Note
The classic integrated frontend which is called "Classic UI" is still available if you are not ready for the new separate frontend.
If you choose to use Classic UI, then do not use the plone.volto
package.
To learn how to modify an existing Plone site to run with Volto, please read Migrating from Plone Classic UI to Volto.
See also
Archetypes#
The deprecated Archetypes content types framework is no longer supported. Add-ons that define a content type must use Dexterity instead.
See also
Some deprecated views have been removed#
In Plone 6 some legacy view aliases have been removed. You can replace them with the new ones based on the following table:
Legacy name |
New name |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
No more temp_folder
or tempstorage
#
The temp_folder
object in the Zope root is no longer created by default.
If the object is there, but it is broken, the standard Plone upgrade procedure will remove it.
For now, you must explicitly disable the temp_folder
if you use buildout:
[instance]
recipe = plone.recipe.zope2instance
zodb-temporary-storage = off
See also
Changed templates to Bootstrap 5 markup#
All templates in core Plone have been updated to use Bootstrap 5 markup. Add-on authors are encouraged to do the same. If you have customized a core template, you should check if your change is still needed, and update it to fit the new markup. Any CSS and JavaScript that relies on a specific structure, or certain IDs or classes, should be checked as well.
See also
Zope 5#
Plone 6.0 means we move from Zope 4 to 5.
This drops support for Python 2.7, drops ZServer
, and removes deprecated code.
See also
Some imports may need to change. Add-on authors should check on Plone 5.2 if their code runs without any deprecation warnings from Zope 4. If no warnings are shown, the add-on should run fine on Zope 5.
See also
Modernize Plone Classic UI theme (Barceloneta)#
The standard theme in Classic UI was updated to Bootstrap 5, CSS variables, and an icon library. If you have a theme that builds on Barceloneta, you most likely need various changes.
It may be best to start with a fresh theme, and try to keep the changes minimal. The training documentation lists three possible theming strategies:
Create a theme based on Barceloneta.
Create a theme from scratch.
Create a theme based on Diazo.
See also
Python#
You may need to use a newer Python version. Supported Python versions are 3.8, 3.9, 3.10, and 3.11. We recommend the most recent version. See https://www.python.org/downloads/ for which Python version is still supported by the Python community.
See also
plone.api.relation
#
The plone.api
package now has a relation
module.
Add-on authors may want to use this to get, create, or delete relations.
See also
Mockup and resource registry redone#
Mockup contains the source of most Classic UI Plone JavaScript.
The compiled version is in plone.staticresources
.
Mockup is now based on Patternslib 9. It uses ES6 module imports instead of RequireJS. Add-ons for Classic UI Plone that use JavaScript should be updated to use ES6 modules as well.
The resource registries and their control panel have been simplified. Add-ons for Classic UI Plone only need to register bundles, not individual resources.
See also
Relations control panel#
Plone 6 has a new control panel for relations, @@inspect-relations
.
As a Manager, you may want to use this control panel to look for and fix possible problems.
See also
Deprecated Unicode property types#
Zope 5 has deprecated the Unicode property types ustring
, ulines
, utext
, and utokens
.
If you use these in your add-on, you should switch to their standard variants string
, lines
, text
, and tokens
.
These behave exactly the same on Python 3.
Plone has an upgrade step that goes through all objects in the site, replacing the deprecated properties with the default ones.
You should avoid adding them to your code.
See also
autoinclude
#
We have replaced z3c.autoinclude
with plone.autoinclude
.
Both are used by add-ons (Python packages) to signal, with an entry point, that Plone must load the ZCML of the add-on.
In most cases, the existing entry point can stay the same.
For example in setup.py
:
entry_points="""
[z3c.autoinclude.plugin]
target = plone
"""
When your package name differs from your module name, you need to specify a differently named entry point.
When your module is named example.alternative
, create this entry point:
entry_points="""
[plone.autoinclude.plugin]
target = plone
module = example.alternative
"""
The includeDependencies
directive is no longer supported.
It was already recommended not to use this directive, as it is too implicit.
In the ZCML files of your add-on, search for includeDependencies
.
Replace all of its instances by explicitly loading any ZCML from other packages used by the add-on.
Here is a sample change from dexterity.membrane
:
- <includeDependencies package="." />
+ <include package="Products.membrane" />
The same change is needed for the no longer supported includeDependenciesOverrides
directive, which may be used in overrides.zcml
.
See also
plone.autoinclude
documentation
collective.dexteritytextindexer
merged#
You can mark fields of a content type as searchable.
You can then find an object in the search form by using any text from these fields.
For this to work, you need to enable the plone.textindexer
behavior on the content type.
For more information, see TextIndexer.
In earlier Plone versions, this feature was available in the collective.dexteritytextindexer
package.
This was merged into Plone 6.0 core, with most code ending up in plone.app.dexterity
.
If you have an add-on or custom code that uses the old package, then this must be upgraded. These are the needed changes:
Remove
collective.dexteritytextindexer
from theinstall_requires
insetup.py
.Update the Python code of your content type code, like this:
-from collective import dexteritytextindexer
+from plone.app.dexterity import textindexer
from plone.app.textfield import RichText
from plone.supermodel import model
...
class IExampleType(model.Schema):
- dexteritytextindexer.searchable("text")
+ textindexer.searchable("text")
text = RichText(...)
In the GenericSetup xml of your content type, use the new behavior:
<property name="behaviors" purge="false">
- <element value="collective.dexteritytextindexer" />
- <element value="collective.dexteritytextindexer.behavior.IDexterityTextIndexer" />
+ <element value="plone.textindexer" />
</property>
Search for any leftovers of
collective.dexteritytextindexer
in your code and replace it.
The in-place upgrade to Plone will replace the two versions of the old behavior with the new one in all content types.
See also
plone.base
package#
Within the Plone code base there are circular dependencies.
Package A uses package B and package B uses package A.
Specifically, Products.CMFPlone
is the main package of Plone where everything comes together.
Products.CMFPlone
depends on a lot of Plone packages.
But these packages often import code from Products.CMFPlone
.
This is done in such a way that it works, but it creates an unclear situation and makes it hard to debug errors when they occur in this implicit dependency chain.
The solution in Plone 6.0 was to create a package called plone.base
.
Some often used code from Products.CMFPlone
and other packages was moved here.
Backwards compatibility imports were kept in place, so this should not cause any breakage in add-ons.
You will get warnings in your logs, unless you have silenced them.
For example when your code has from Products.CMFPlone.utils import base_hasattr
you will see:
DeprecationWarning: base_hasattr is deprecated.
Import from plone.base.utils instead (will be removed in Plone 7)
If the add-on only needs to support Plone 6, you can change the code like this:
- from Products.CMFPlone.utils import base_hasattr
+ from plone.base.utils import base_hasattr
If the add-on needs to support both Plone 5 and 6, this works and avoids the warning:
try:
from plone.base.utils import base_hasattr
except ImportError:
# BBB for Plone 5
from Products.CMFPlone.utils import base_hasattr
See also
Support for modern image scales#
In Plone 5.2 the following image scales were available, with scale name, width, and height:
large 768:768
preview 400:400
mini 200:200
humb 128:128
tile 64:64
icon 32:32
listing 16:16
Plone 6.0 changes them:
huge 1600:65536
great 1200:65536
larger 1000:65536
large 800:65536
teaser 600:65536
preview 400:65536
mini 200:65536
thumb 128:128
tile 64:64
icon 32:32
listing 16:16
The biggest scale now has a width of 1600 instead of 768.
The
large
scale was made slightly bigger: from 768 to 800.All scales above
mini
have a height of 65536. This does not mean you get an extremely high image. It means only the width is taken into account when resizing the image. This is a better fit for most modern themes.
Note
The standard Plone upgrade only adds the completely new scales: huge
, great
, larger
, and teaser
.
It leaves the other scales untouched.
This is to avoid strange differences between old and new images.
For example, old images would otherwise have a large scale with width 768, where for new images this would be width 800.
See also
Image pre-scaling#
In Plone 6, we have made a split between generating a URL for an image scale and actually scaling the image. Why would you want this?
As an add-on author, you create a template and you want to show an uploaded image with the preview scale. The code would be like this:
<img tal:define="images context/@@images"
tal:replace="structure python:images.tag('image', scale='preview')" />
In Plone 5 this creates a scale of the image, using the Pillow imaging library. In Plone 6, the scaled image is not yet created at this point. The scaled image is only created when the browser actually requests the image.
This is good, because for various reasons, the browser may never actually ask for this scaled image. For example, the browser may be on a mobile phone with the images turned off to prevent using costly band width. Also, when the tag contains source sets for HiDPI or picture variants, the browser may see five possible images and only choose to download one of them.
In Plone 6, when generating a tag for, as in this case, the preview
scale, a unique URL is generated, and information for this scale is pre-registered.
Only when the browser requests the scaled image at this URL, does Plone generate the scale.
This avoids generating image scales that never get used.
This performance improvement makes two other image improvements possible. These follow in the sections directly below.
Add-on authors do not have to change anything.
But it is a good idea to check how you are using images, otherwise you miss out on this improvement.
If you call the tag
method like above, you are good.
If you use the scale
method and then use its tag
method, then you should change:
<img tal:define="images context/@@images"
- tal:replace="structure python:images.scale('image', scale='preview').tag()" />
+ tal:replace="structure python:images.tag('image', scale='preview')" />
Alternatively, you can explicitly use the new pre
argument, but this will fail on Plone 5:
<img tal:define="images context/@@images"
tal:replace="structure python:images.scale('image', scale='preview', pre=True).tag()" />
Note
There now is an image test page that shows several scales of an image, in various modes.
In your browser, go to an image, and add /@@images-test
to the end of the URL.
Responsive image support#
Responsive image support was added with picture tags. For more information, see Responsive image support.
In an add-on nothing needs to be changed.
But if you want to use the responsive image support, you should use the picture
method:
<img tal:define="images context/@@images"
- tal:replace="structure python:images.tag('image', scale='preview')" />
+ tal:replace="structure python:images.picture('image', picture_variant='small')" />
Store image scale info in catalog metadata#
When you add or edit an image, Plone 6 pre-registers all scales and stores information about them in the portal catalog. The catalog brain of an image then has all the needed information about each scale, especially the unique URL, width, and height. This is used on lists of images to be able to show a scale in a tag without waking up the image objects from the database. In other words, this speeds up pages that contain lots of images.
Add-on authors do not have to change anything, as this happens automatically. If you have a very special use case, you can influence this with some new adapters.
Note
When upgrading your Plone Site to Plone 6.0, the in-place migration finds all images in your site. It then adds the scale information to the catalog. This may take a long time. You can disable this with an environment variable:
export UPDATE_CATALOG_FOR_IMAGE_SCALES=0
In that case, you are advised to add the image_scales
column manually to the catalog later.
See also
New version of TinyMCE#
Plone 6 ships with a new version of TinyMCE.
While Plone 5.2 ships with TinyMCE 4.7, Plone 6.0 ships with TinyMCE 5.10.
The TinyMCE integration pat-tinymce
has also changed, but the configuration options have been almost kept the same and are likely to be compatible with your existing installation.
The configuration changes are:
Added configuration options
text.enableImageZoom
,defaultSrcset
,imageCaptioningEnabled
, andtiny.language
.Removed configuration option
imageScales
.Option values changed for
imageClasses
.
TinyMCE templates#
In Plone 6, the TinyMCE template plugin is built-in and can be enabled via a checkbox.
Whereas in Plone 5, you had to enable the template plugin as an external plugin via the custom_plugins
configuration option.
The template registration is the same as before, but in Plone 6 your templates need to have a description
.
Otherwise TinyMCE will throw a JavaScript error, and the templates won't be usable at all.
The following example registry.xml
may be used for configuring TinyMCE with some templates.
<records interface="Products.CMFPlone.interfaces.controlpanel.ITinyMCESchema"
prefix="plone">
<value key="plugins" purge="False">
<element>template</element>
</value>
<value key="custom_plugins" purge="True">
<!-- Remove the old TinyMCE template plugin -->
</value>
<value key="templates">
[
{
"title": "Template 1",
"description": "This is an example template",
"url": "++plone++my.site/template1.html"
},
{
"title": "Template 2",
"description": "This is another example template",
"url": "++plone++my.site/template2.html"
}
]
</value>
</records>
Please make sure you write valid JSON for the template
option.
See also
See also Migrating from TinyMCE 4 to TinyMCE 5.
Viewlets#
Plone 6.0 renames various viewlets or moves them to a different viewlet manager. This is because some viewlet names contained the name of a viewlet manager. This didn't always match the name of their actual viewlet manager, especially after moving them. Plone 6.0 removes such references from the viewlet names to avoid confusion.
Plone 6.0 removes the
plone.header
viewlet fromplone.portaltop
manager, making it empty.Plone 6.0 renames the
plone.abovecontenttitle.documentactions
viewlet toplone.documentactions
, and moves it from managerplone.belowcontentbody
toplone.belowcontent
.Plone 6.0 renames the
plone.abovecontenttitle.socialtags
viewlet toplone.socialtags
. It remains in managerplone.abovecontenttitle
.Plone 6.0 renames the
plone.belowcontentbody.relateditems
viewlet toplone.relateditems
. It remains in managerplone.belowcontentbody
.Plone 6.0 removes the
plone.manage_portlets_fallback
viewlet from theplone.belowcontent
manager.Plone 6.0 renames the
plone.belowcontenttitle.documentbyline
viewlet toplone.documentbyline
. It remains in managerplone.belowcontenttitle
.Plone 6.0 renames the
plone.belowcontenttitle.keywords
viewlet toplone.keywords
, and moves it from managerplone.belowcontent
toplone.belowcontentbody
.Plone 6.0 adds the
plone.rights
viewlet in managerplone.belowcontentbody
.
The names in the following table have had the namespace plone.
removed from them for display purposes only.
In your code, you should use the object's plone.
namespace as a prefix.
This table shows the same information, but in tabular form.
5.2 viewlet name |
5.2 viewlet manager |
6.0 viewlet name |
6.0 viewlet manager |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Plone 6.0 makes changes to two viewlet managers:
Plone 6.0 removes the
plone.documentactions
(IDocumentActions
) viewlet manager. In Plone 5.2 it was already empty.Plone 6.0 adds the
plone.belowcontentdescription
(IBelowContentDescription
) viewlet manager. By default this has no viewlets.
One final change is that Plone 6.0 moves the plone.footer
viewlet from plone.app.layout/viewlets
to plone.app.portlets
.
The viewlet remains in manager plone.portalfooter
.
It renders the portlets from the plone.footerportlets
portlet manager.
Boolean fields#
Since zope.schema==6.1.0
, all zope.schema.Bool
fields must have a required=False
attribute.
This allows you to either tick or not tick the checkbox, submit the form, and process the field with either its value when ticked or None
when unticked.
Otherwise, you can't save the form without ticking the checkbox, which effectively makes the field value always True
.