The Admin with Versioning

Versioning in django CMS provides powerful tools to manage content and grouper models in the admin interface. This chapter explains the default patterns and customization options for integrating versioning into your admin classes.

Proxy models of djangocms_versioning.models.Version are generated for each registered content model, allowing customization of the version table by model.

Default Pattern

The default pattern is to set the grouper_admin_mixin property to "__default__", which applies the DefaultGrouperVersioningAdminMixin to the grouper model admin. This mixin ensures that state indicators and admin list actions are displayed consistently.

Admin Options Overview

Overview on versioning admin options: Grouper models

Versioning state

Grouper Model Admin

Default: Indicators, drop down menu

class GrouperAdmin(
    DefaultGrouperVersioningAdminMixin,
    GrouperModelAdmin
):
    list_display = ...

Indicators, drop down menu (fix the current default)

class GrouperAdmin(
    ExtendedGrouperVersionAdminMixin,
    StateIndicatorMixin,
    GrouperModelAdmin
):
    list_display = ...

Text, no interaction

class GrouperAdmin(
    ExtendedGrouperVersionAdminMixin,
    GrouperModelAdmin
):
    list_display = ...
Overview on versioning admin options: Content models

Versioning state

Content Model Admin

Text, no interaction

class ContentAdmin(
    ExtendedVersionAdminMixin,
    admin.ModelAdmin
)

Indicators, drop down menu

class ContentAdmin(
    ExtendedIndicatorVersionAdminMixin,
    admin.ModelAdmin,
)

Adding Versioning to Content Model Admins

The ExtendedVersionAdminMixin provides fields and actions related to versioning, such as:

  • Author

  • Modified date

  • Versioning state

  • Preview action

  • Edit action

  • Version list action

Example:

class PostContentAdmin(ExtendedVersionAdminMixin, admin.ModelAdmin):
    list_display = ["title"]

The ExtendedVersionAdminMixin also has functionality to alter fields from other apps. By adding the extended_admin_field_modifiers to a given app’s cms_config, in the form of a dictionary of {model_name: {field: method}}, the admin for the model will alter the field using the method provided.

# cms_config.py
def post_modifier(obj, field):
    return obj.get(field) + " extra field text!"

class PostCMSConfig(CMSAppConfig):
    # Other versioning configurations...
    admin_field_modifiers = [
        {PostContent: {"title": post_modifier}},
    ]

Given the code sample above, “This is how we add” would be displayed as “this is how we add extra field text!” in the changelist of PostAdmin.

Adding State Indicators

djangocms-versioning provides status indicators for django CMS’ content models, you may know them from the page tree in django-cms:

../_images/Status-indicators.png

You can use these on your content model’s changelist view admin by adding the following mixin to the model’s Admin class:

class MyContentModelAdmin(StateIndicatorMixin, admin.ModelAdmin):
    list_display = [..., "state_indicator", ...]

Note

For grouper models, ensure that the admin instance defines properties for each extra grouping field (e.g., self.language). If you derive your admin class from GrouperModelAdmin, this behavior is automatically handled.

Otherwise, this is typically set in the get_changelist_instance method, e.g., by getting the language from the request. The page tree, for example, keeps its extra grouping field (language) as a get parameter to avoid mixing language of the user interface and language that is changed.

def get_changelist_instance(self, request):
    """Set language property and remove language from changelist_filter_params"""
    if request.method == "GET":
        request.GET = request.GET.copy()
        for field in versionables.for_grouper(self.model).extra_grouping_fields:
            value = request.GET.pop(field, [None])[0]
            # Validation is recommended: Add clean_language etc. to your Admin class!
            if hasattr(self, f"clean_{field}"):
                value = getattr(self, f"clean_{field}")(value):
            setattr(self, field) = value
        # Grouping field-specific cache needs to be cleared when they are changed
        self._content_cache = {}
    instance = super().get_changelist_instance(request)
    # Remove grouping fields from filters
    if request.method == "GET":
        for field in versionables.for_grouper(self.model).extra_grouping_fields:
            if field in instance.params:
                del instance.params[field]
    return instance

Combining Status Indicators and Versioning

To combine both status indicators and versioning fields, use the ExtendedIndicatorVersionAdminMixin:

class MyContentModelAdmin(ExtendedIndicatorVersionAdminMixin, admin.ModelAdmin):
    ...

The versioning state and version list action are replaced by the status indicator and its context menu, respectively.

Add additional actions by overwriting the self.get_list_actions() method and calling super().

Adding Versioning to Grouper Model Admins

For grouper models, use the ExtendedGrouperVersionAdminMixin to add versioning fields:

class PostAdmin(ExtendedGrouperVersionAdminMixin, GrouperModelAdmin):
    list_display = ["title", "get_author", "get_modified_date", "get_versioning_state"]

To also add state indicators, include the StateIndicatorMixin:

class PostAdmin(ExtendedGrouperVersionAdminMixin, StateIndicatorMixin, GrouperModelAdmin):
    list_display = ["title", "get_author", "get_modified_date", "state_indicator"]