Versioning contract¶
Django CMS uses a contract-based approach for versioning, allowing different versioning implementations to integrate with the CMS and its ecosystem. djangocms-versioning defines the versioning contract for django CMS. This section describes the contract that djangocms-versioning does implement and other versioning packages must implement to work with django CMS.
Overview¶
The contract is implemented through django CMS’s CMSAppExtension mechanism in the
cms_config.py module. When installed, djangocms-versioning becomes the versioning
provider for all content types that register with it—including django CMS pages,
aliases, stories, and any custom content models.
Note
djangocms-versioning is the reference implementation endorsed by the django CMS Association.
Contract definition¶
The contract is defined in djangocms-versioning’s cms_config.py using the
contract class attribute, a 2-tuple consisting of the contract name ("djangocms_versioning")
and the contract class (VersionableItem):
from cms.app_base import CMSAppExtension
from .datastructures import VersionableItem
class VersioningCMSExtension(CMSAppExtension):
contract = "djangocms_versioning", VersionableItem
def __init__(self):
self.versionables = []
def configure_app(self, cms_config):
# Process the versioning configuration
if hasattr(cms_config, "versioning"):
self.handle_versioning_setting(cms_config)
# ... additional setup
The contract attribute is a tuple of:
The contract name (
"djangocms_versioning")The
VersionableItemclass that apps use to register their content models
This allows other packages to register for versioning without importing directly from djangocms-versioning, enabling alternative implementations to provide the same contract.
Contract components¶
VersionableItem class¶
The VersionableItem class defines how a content model participates in versioning.
At minimum, it must accept:
content_modelThe Django model class that stores versioned content (the content model).
grouper_field_nameThe name of the foreign key field on the content model that points to the grouper model.
copy_functionAn (optional) callable that creates a copy of a content object when creating new versions.
Additional optional parameters are djangocms-versioning-specific and may include:
extra_grouping_fields: Additional fields for grouping versions (e.g.,language)on_publish,on_unpublish,on_draft_create,on_archive: Lifecycle hookspreview_url: Function to generate preview URLs for versionscontent_admin_mixin: Custom admin mixin for the content modelgrouper_admin_mixin: Custom admin mixin for the grouper model
Manager modifications¶
A versioning package typically modifies the content model’s managers:
objectsmanagerShould filter to return only published content by default, ensuring unpublished content never leaks to the public.
admin_managerShould provide access to all content versions, for use in admin contexts only.
These managers enable the pattern:
# Public queries - only published content
PostContent.objects.filter(...)
# Admin queries - all versions accessible
PostContent.admin_manager.filter(...)
Registration mechanism¶
Content models register for versioning via cms_config.py:
# myapp/cms_config.py
from cms.app_base import CMSAppConfig
from .models import MyContent
class MyAppConfig(CMSAppConfig):
djangocms_versioning_enabled = True # <contract>_enabled = True
def __init__(self, app):
super().__init__(app)
# Dynamically get the installed contract object
VersionableItem = self.get_contract("djangocms_versioning")
self.versioning = [
VersionableItem(
content_model=MyContent,
grouper_field_name="grouper",
grouper_admin_mixin="__default__",
),
]
The djangocms_versioning_enabled = True attribute signals that this app wants to
use the versioning extension. The get_contract("djangocms_versioning") call retrieves the
VersionableItem class from the installed versioning package, allowing the app to
register its content models for versioning.
Implementing alternative versioning packages¶
Alternative versioning packages must follow the contract defined by djangocms-versioning. Specifically, they must:
Export a VersionableItem class (or compatible equivalent) that other packages can discover and use for registration.
Process the
versioningattribute fromCMSAppConfigsubclasses that havedjangocms_versioning_enabled = True.Modify content model managers to provide the
objects/admin_managerpattern expected by django CMS and ecosystem packages.(Optional) Provide version state information for the CMS toolbar and admin interfaces. djangocms-versioning does this by injecting a
content_indicatormethod onto content models that returns status strings (e.g.,"published","draft","dirty"). Alternative implementations may define their own states or omit this functionality.
Ecosystem compatibility¶
Packages in the django CMS ecosystem (such as djangocms-alias and djangocms-stories) register their content models using the versioning contract. When you install a versioning package, it becomes responsible for managing versions of all registered content types.
This means:
Switching versioning packages affects all versioned content across your site
Alternative implementations must handle registrations from ecosystem packages
The version states and workflow defined by your versioning package apply universally
See also¶
Integrating Versioning for integrating your models with versioning
Advanced configuration for customizing versioning behavior
Version Model API for the Version model reference