3.4 release notes
The most significant change in this release is the removal of revision support (i.e. undo/redo/recover functionality on pages) from the core django CMS. This functionality will be reinstated as an optional addon in due course, but in the meantime, that functionality is not available.
What’s new in 3.4
- Changed the way CMS plugins are rendered. The HTML
div
withcms-plugin
class is no longer rendered around every CMS plugin. Instead a combination oftemplate
tags and JavaScript is used to add event handlers and plugin data directly to the plugin markup. This fixes most of the rendering issues caused by the extra markup. - Changed asset cache-busting implementation, which is now handled by a path change, rather than the
GET
parameter. - Added the option to copy pages in the page tree using the drag and drop interface.
- Made it possible to use multi-table inheritance for Page/Title extensions.
- Refactored plugin rendering functionality to speed up loading time in both structure and content modes.
- Added a new
Shift
+Space
shortcut to switch between structure and content mode while highlighting the current plugin, revealing its position. - Improved keyboard navigation
- Added help modal about available short-cuts
- Added fuzzy matching to the plugin picker.
- Changed the
downcast_plugins
utility to return a generator instead of a list. - Fixed a bug that caused an aliased placeholder to show in structure mode.
- Fixed a bug that prevented aliased content from showing correctly without publishing the page first.
- Added help text to an
Alias
plugin change form when attached to a page to show the content editor where the content is aliased from. - Removed revision support from django CMS core. As a result both
CMS_MAX_PAGE_HISTORY_REVERSIONS
andCMS_MAX_PAGE_PUBLISH_REVERSIONS
settings are no longer supported, as well as thewith_revision
parameter incms.api.create_page
andcms.api.create_title
. - In
cms.plugin_base.CMSPluginBase
methodsget_child_classes
andget_parent_classes
now are implemented as a@classmethod
.
Upgrading to 3.4
A database migration is required because the default value of CMSPlugin.position was set to 0 instead of null.
Please make sure that your current database is consistent and in a healthy state, and make a copy of the database before proceeding further.
Then run:
python manage.py migrate
python manage.py cms fix-tree
Backward incompatible changes
Apphooks & Toolbars
As per our deprecation policy we’ve now removed the backwards compatible shim for cms_app.py
and cms_toolbar.py
. If you have not done so already, please rename these to cms_apps.py
and cms_toolbars.py
.
Permissions
The permissions system was heavily refactored. As a result, several internal functions and methods have been removed or changed.
Functions removed:
user_has_page_add_perm
has_page_add_permission
has_page_add_permission_from_request
has_any_page_change_permissions
has_auth_page_permission
has_page_change_permission
has_global_page_permission
has_global_change_permissions_permission
has_generic_permission
load_view_restrictions
get_any_page_view_permissions
The following methods were changed to require a user parameter instead of a request:
Page.has_view_permission
Page.has_add_permission
Page.has_change_permission
Page.has_delete_permission
Page.has_delete_translation_permission
Page.has_publish_permission
Page.has_advanced_settings_permission
Page.has_change_permissions_permission
Page.has_move_page_permission
These are also deprecated in favour of their counterparts in cms.utils.page_permissions
.
To keep consistency with both django CMS permissions and Django permissions, we’ve modified the vanilla permissions system (CMS_PERMISSIONS = False
) to require users to have certain Django permissions to perform an action.
Here’s an overview:
Action | Permission required |
---|---|
Add Page | Can Add Page & Can Change Page |
Change Page | Can Change Page |
Delete Page | Can Change Page & Can Delete Page |
Move Page | Can Change Page |
Publish Page | Can Change Page & Can Publish Page |
This change will only affect non-superuser staff members.
Warning
If you have a custom Page
extension with a configured toolbar, please see the updated example. It uses the new permission internals.
Manual plugin rendering
We’ve rewritten the way plugins and placeholders are rendered. As a result, if you’re manually rendering plugins and placeholders you’ll have to adapt your code to match the new rendering mechanism.
To render a plugin programmatically, you will need a context and request object.
Warning
Manual plugin rendering is not a public API, and as such it’s subject to change without notice.
from django.template import RequestContext
from cms.plugin_rendering import ContentRenderer
def render_plugin(request, plugin):
renderer = ContentRenderer(request)
context = RequestContext(request)
# Avoid errors if plugin require a request object
# when rendering.
context['request'] = request
return renderer.render_plugin(plugin, context)
Like a plugin, to render a placeholder programmatically, you will need a context and request object.
Warning
Manual placeholder rendering is not a public API, and as such it’s subject to change without notice.
from django.template import RequestContext
from cms.plugin_rendering import ContentRenderer
def render_placeholder(request, placeholder):
renderer = ContentRenderer(request)
context = RequestContext(request)
# Avoid errors if plugin require a request object
# when rendering.
context['request'] = request
content = renderer.render_placeholder(
placeholder,
context=context,
)
return content