From 2846080d46de943beb876ffa69ed79fe56b33631 Mon Sep 17 00:00:00 2001 From: Stefan Wehrmeyer Date: Tue, 5 Aug 2025 21:47:10 +0100 Subject: [PATCH 1/4] feat: Use `get_full_url` on versioned content if available This allows viewing versioned content on different sites --- djangocms_versioning/admin.py | 11 ++++++++--- djangocms_versioning/cms_toolbars.py | 4 +++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/djangocms_versioning/admin.py b/djangocms_versioning/admin.py index e008b202..b53d2088 100644 --- a/djangocms_versioning/admin.py +++ b/djangocms_versioning/admin.py @@ -1101,9 +1101,14 @@ def publish_view(self, request, object_id): self.message_user(request, _("Version published")) # Redirect to published? - if conf.ON_PUBLISH_REDIRECT == "published": - if hasattr(version.content, "get_absolute_url"): - requested_redirect = requested_redirect or version.content.get_absolute_url() + if not requested_redirect and conf.ON_PUBLISH_REDIRECT == "published": + if hasattr(version.content, "get_full_url"): + full_url = version.content.get_full_url() + if full_url: + # Can't resolve full_url, redirect directly to it + return redirect(full_url) + elif hasattr(version.content, "get_absolute_url"): + requested_redirect = version.content.get_absolute_url() return self._internal_redirect(requested_redirect, redirect_url) diff --git a/djangocms_versioning/cms_toolbars.py b/djangocms_versioning/cms_toolbars.py index f4a29df0..be430d66 100644 --- a/djangocms_versioning/cms_toolbars.py +++ b/djangocms_versioning/cms_toolbars.py @@ -258,7 +258,9 @@ def _add_view_published_button(self): if not published_version: return - url = published_version.get_absolute_url() if hasattr(published_version, "get_absolute_url") else None + url = published_version.get_full_url() if hasattr(published_version, "get_full_url") else None + if not url and hasattr(published_version, "get_absolute_url"): + url = published_version.get_absolute_url() if url and (self.toolbar.edit_mode_active or self.toolbar.preview_mode_active): item = ButtonList(side=self.toolbar.RIGHT) item.add_button( From 712f59cefa999396b532d5295fdab3f7939d268a Mon Sep 17 00:00:00 2001 From: Stefan Wehrmeyer Date: Tue, 5 Aug 2025 21:47:48 +0100 Subject: [PATCH 2/4] fix: Add a site query paramter to page admin change form --- .../templates/admin/djangocms_versioning/page/change_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_versioning/templates/admin/djangocms_versioning/page/change_form.html b/djangocms_versioning/templates/admin/djangocms_versioning/page/change_form.html index 919dbec3..f4929c8f 100644 --- a/djangocms_versioning/templates/admin/djangocms_versioning/page/change_form.html +++ b/djangocms_versioning/templates/admin/djangocms_versioning/page/change_form.html @@ -34,7 +34,7 @@ -
+ {% csrf_token %} {% block form_top %}{% endblock %} From 311f8297c090ce983e05baa906379f10dc90583e Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Fri, 7 Nov 2025 16:41:57 +0100 Subject: [PATCH 3/4] feat: Use django-cms core's get_object_live_url if available --- djangocms_versioning/admin.py | 11 ++++------- djangocms_versioning/cms_toolbars.py | 13 +++++++------ djangocms_versioning/helpers.py | 23 ++++++++++++++++++----- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/djangocms_versioning/admin.py b/djangocms_versioning/admin.py index b53d2088..8278735e 100644 --- a/djangocms_versioning/admin.py +++ b/djangocms_versioning/admin.py @@ -46,8 +46,10 @@ content_is_unlocked_for_user, create_version_lock, get_admin_url, + get_current_site, get_editable_url, get_latest_admin_viewable_content, + get_object_live_url, get_preview_url, proxy_model, remove_version_lock, @@ -1102,13 +1104,8 @@ def publish_view(self, request, object_id): # Redirect to published? if not requested_redirect and conf.ON_PUBLISH_REDIRECT == "published": - if hasattr(version.content, "get_full_url"): - full_url = version.content.get_full_url() - if full_url: - # Can't resolve full_url, redirect directly to it - return redirect(full_url) - elif hasattr(version.content, "get_absolute_url"): - requested_redirect = version.content.get_absolute_url() + if hasattr(version.content, "get_absolute_url"): + requested_redirect = get_object_live_url(version.content, site=get_current_site(request)) return self._internal_redirect(requested_redirect, redirect_url) diff --git a/djangocms_versioning/cms_toolbars.py b/djangocms_versioning/cms_toolbars.py index be430d66..dd327e34 100644 --- a/djangocms_versioning/cms_toolbars.py +++ b/djangocms_versioning/cms_toolbars.py @@ -1,6 +1,5 @@ from collections import OrderedDict from copy import copy -from typing import Optional from cms import __version__ as cms_version from cms.cms_toolbars import ( @@ -31,7 +30,9 @@ from djangocms_versioning.conf import ALLOW_DELETING_VERSIONS, LOCK_VERSIONS from djangocms_versioning.constants import DRAFT from djangocms_versioning.helpers import ( + get_current_site, get_latest_admin_viewable_content, + get_object_live_url, version_list_url, ) from djangocms_versioning.models import Version @@ -258,9 +259,9 @@ def _add_view_published_button(self): if not published_version: return - url = published_version.get_full_url() if hasattr(published_version, "get_full_url") else None - if not url and hasattr(published_version, "get_absolute_url"): - url = published_version.get_absolute_url() + url = None + if hasattr(published_version, "get_absolute_url"): + url = get_object_live_url(published_version, site=get_current_site(self.toolbar.request)) if url and (self.toolbar.edit_mode_active or self.toolbar.preview_mode_active): item = ButtonList(side=self.toolbar.RIGHT) item.add_button( @@ -299,10 +300,10 @@ class VersioningPageToolbar(PageToolbar): """ def __init__(self, *args, **kwargs): - self.page_content: Optional[PageContent] = None + self.page_content: PageContent | None = None super().__init__(*args, **kwargs) - def get_page_content(self, language: Optional[str] = None) -> PageContent: + def get_page_content(self, language: str | None = None) -> PageContent: # This method overwrites the method in django CMS core. Not necessary # for django CMS 4.2+ if not language: diff --git a/djangocms_versioning/helpers.py b/djangocms_versioning/helpers.py index 03e804b9..343a6819 100644 --- a/djangocms_versioning/helpers.py +++ b/djangocms_versioning/helpers.py @@ -2,7 +2,6 @@ import warnings from collections.abc import Iterable from contextlib import contextmanager -from typing import Optional from cms.models import Page, PageContent, Placeholder from cms.toolbar.utils import get_object_edit_url, get_object_preview_url @@ -17,7 +16,7 @@ from django.http import HttpRequest from django.template.loader import render_to_string from django.utils.encoding import force_str -from django.utils.translation import get_language +from django.utils.translation import get_language, override as force_language from . import versionables from .conf import EMAIL_NOTIFICATIONS_FAIL_SILENTLY @@ -28,6 +27,20 @@ except ImportError: emit_content_change = None +try: + from cms.toolbar.utils import get_object_live_url + from cms.utils import get_current_site +except ImportError: # cms < 5.1 + def get_object_live_url(obj, language=None, site=None) -> str: + with force_language(language): + return obj.get_absolute_url() + return None + + def get_current_site(request) -> models.Model: + from django.contrib.sites.models import Site + + return Site.objects.get_current() + def is_editable(content_obj: models.Model, request: HttpRequest) -> bool: """Check of content_obj is editable""" @@ -71,7 +84,7 @@ def _replace_admin_for_model(modeladmin: type[admin.ModelAdmin], mixin: type, ad admin_site.register(modeladmin.model, new_admin_class) -def replace_admin_for_models(pairs: tuple[type[models.Model], type], admin_site: Optional[admin.AdminSite] = None): +def replace_admin_for_models(pairs: tuple[type[models.Model], type], admin_site: admin.AdminSite | None = None): """ :param models: List of (model class, admin mixin class) tuples :param admin_site: AdminSite instance @@ -86,7 +99,7 @@ def replace_admin_for_models(pairs: tuple[type[models.Model], type], admin_site: _replace_admin_for_model(modeladmin, mixin, admin_site) -def register_versionadmin_proxy(versionable, admin_site: Optional[admin.AdminSite] = None): +def register_versionadmin_proxy(versionable, admin_site: admin.AdminSite | None = None): """Creates a model admin class based on `VersionAdmin` and registers it with `admin_site` for `versionable.version_model_proxy`. @@ -281,7 +294,7 @@ def get_content_types_with_subclasses(models: Iterable[type[models.Model]], usin def get_preview_url( - content_obj: models.Model, language: Optional[str] = None + content_obj: models.Model, language: str | None = None ) -> str: """If the object is editable the cms preview view should be used, with the toolbar. This method provides the URL for it. It falls back the standard change view From 1a4f32052ba06b2a67e5ea0264987f2e804fd615 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Fri, 7 Nov 2025 16:47:21 +0100 Subject: [PATCH 4/4] fix: Linting issues --- djangocms_versioning/helpers.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/djangocms_versioning/helpers.py b/djangocms_versioning/helpers.py index 92fd726d..beb70d7a 100644 --- a/djangocms_versioning/helpers.py +++ b/djangocms_versioning/helpers.py @@ -30,13 +30,14 @@ emit_content_change = None try: - from cms.toolbar.utils import get_object_live_url - from cms.utils import get_current_site -except ImportError: # cms < 5.1 + # django CMS >= 5.1 + from cms.toolbar.utils import get_object_live_url # noqa F401 + from cms.utils import get_current_site # noqa F401 +except ImportError: + # cms < 5.1 def get_object_live_url(obj, language=None, site=None) -> str: with force_language(language): return obj.get_absolute_url() - return None def get_current_site(request) -> models.Model: from django.contrib.sites.models import Site