From 9d284dbfb69155fe08977089a739a0572abb7264 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Tue, 3 Feb 2026 18:23:26 +0100 Subject: [PATCH 1/8] fix: Show fallback languages if changelist view --- djangocms_alias/models.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/djangocms_alias/models.py b/djangocms_alias/models.py index 2cfc9583..1d14f21e 100644 --- a/djangocms_alias/models.py +++ b/djangocms_alias/models.py @@ -19,7 +19,6 @@ from parler.models import TranslatableModel, TranslatedFields from .constants import CHANGE_ALIAS_URL_NAME, CHANGE_CATEGORY_URL_NAME -from .utils import is_versioning_enabled __all__ = [ "Category", @@ -158,15 +157,18 @@ def objects_using(self): def get_name(self, language=None): content = self.get_content(language, show_draft_content=True) + if not content: + content = next(iter(self._content_cache.values()), None) name = getattr(content, "name", f"Alias {self.pk} (No content)") - if is_versioning_enabled() and content: + try: from djangocms_versioning.constants import DRAFT version = content.versions.first() if version.state == DRAFT: return f"{name} (Not published)" - + except (ImportError, ModuleNotFoundError, AttributeError): + pass return name def get_content(self, language=None, show_draft_content=False): @@ -180,10 +182,9 @@ def get_content(self, language=None, show_draft_content=False): qs = self.contents(manager="admin_manager").latest_content() else: qs = self.contents.all() - qs = qs.filter(language=language) - - self._content_cache[language] = qs.first() - return self._content_cache[language] + for content in qs: + self._content_cache.setdefault(content.language, content) + return self._content_cache.get(language) def get_placeholder(self, language=None, show_draft_content=False): content = self.get_content(language=language, show_draft_content=show_draft_content) From 06cd42540e3e78b29e3fa9bac010e0667c37e514 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Tue, 3 Feb 2026 21:01:13 +0100 Subject: [PATCH 2/8] feat: Respoect contracr object for versioning --- djangocms_alias/cms_config.py | 53 +++++++++++++++++++---------------- djangocms_alias/filters.py | 3 -- djangocms_alias/utils.py | 24 ++++++++++++---- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/djangocms_alias/cms_config.py b/djangocms_alias/cms_config.py index ac9b5d35..f5902917 100644 --- a/djangocms_alias/cms_config.py +++ b/djangocms_alias/cms_config.py @@ -7,6 +7,7 @@ from .cms_wizards import create_alias_wizard from .models import AliasContent, AliasPlugin, copy_alias_content from .rendering import add_static_alias_js, render_alias_content +from .utils import get_versionable_item try: apps.get_app_config("djangocms_internalsearch") @@ -14,8 +15,6 @@ except (ImportError, LookupError): AliasContentConfig = None -djangocms_versioning_installed = apps.is_installed("djangocms_versioning") - class AliasCMSConfig(CMSAppConfig): cms_enabled = True @@ -23,31 +22,37 @@ class AliasCMSConfig(CMSAppConfig): moderated_models = [AliasContent] cms_wizards = [create_alias_wizard] - djangocms_moderation_enabled = getattr(settings, "MODERATING_ALIAS_MODELS_ENABLED", True) - djangocms_versioning_enabled = getattr(settings, "VERSIONING_ALIAS_MODELS_ENABLED", djangocms_versioning_installed) + def __init__(self, app_config): + VersionableItem = get_versionable_item(self) + self.djangocms_moderation_enabled = getattr(settings, "MODERATING_ALIAS_MODELS_ENABLED", True) + self.djangocms_versioning_enabled = getattr( + settings, "VERSIONING_ALIAS_MODELS_ENABLED", VersionableItem is not None + ) - if djangocms_versioning_enabled: - from cms.utils.i18n import get_language_tuple - from djangocms_versioning import __version__ as djangocms_versioning_version - from djangocms_versioning.datastructures import VersionableItem + if self.djangocms_versioning_enabled: + from cms.utils.i18n import get_language_tuple - if PackageVersion(djangocms_versioning_version) < PackageVersion("2.4"): # pragma: no cover - raise ImportError( - "djangocms_versioning >= 2.4.0 is required for djangocms_alias to work properly." - " Please upgrade djangocms_versioning." - ) + if not VersionableItem: + from djangocms_versioning import __version__ as djangocms_versioning_version + from djangocms_versioning.datastructures import VersionableItem - versioning = [ - VersionableItem( - content_model=AliasContent, - grouper_field_name="alias", - extra_grouping_fields=["language"], - version_list_filter_lookups={"language": get_language_tuple}, - copy_function=copy_alias_content, - grouper_selector_option_label=lambda obj, lang: obj.get_name(lang), - grouper_admin_mixin="__default__", - ), - ] + if PackageVersion(djangocms_versioning_version) < PackageVersion("2.4"): # pragma: no cover + raise ImportError( + "djangocms_versioning >= 2.4.0 is required for djangocms_alias to work properly." + " Please upgrade djangocms_versioning." + ) + + self.versioning = [ + VersionableItem( + content_model=AliasContent, + grouper_field_name="alias", + extra_grouping_fields=["language"], + version_list_filter_lookups={"language": get_language_tuple}, + copy_function=copy_alias_content, + grouper_selector_option_label=lambda obj, lang: obj.get_name(lang), + grouper_admin_mixin="__default__", + ), + ] djangocms_references_enabled = getattr(settings, "REFERENCES_ALIAS_MODELS_ENABLED", True) reference_fields = [ diff --git a/djangocms_alias/filters.py b/djangocms_alias/filters.py index b1f7272f..7a5e41bd 100644 --- a/djangocms_alias/filters.py +++ b/djangocms_alias/filters.py @@ -4,7 +4,6 @@ from django.utils.translation import get_language from django.utils.translation import gettext_lazy as _ -from .cms_config import AliasCMSConfig from .constants import ( CATEGORY_FILTER_PARAM, SITE_FILTER_NO_SITE_VALUE, @@ -12,8 +11,6 @@ ) from .models import Category -djangocms_versioning_enabled = AliasCMSConfig.djangocms_versioning_enabled - class SiteFilter(admin.SimpleListFilter): title = _("Site") diff --git a/djangocms_alias/utils.py b/djangocms_alias/utils.py index 4bfbfccc..6822c52a 100644 --- a/djangocms_alias/utils.py +++ b/djangocms_alias/utils.py @@ -1,14 +1,26 @@ +from functools import cache + from django.apps import apps -def is_versioning_enabled(): +@cache +def get_versionable_item(cms_config) -> type | None: + if hasattr(cms_config, "get_contract"): + return cms_config.get_contract("djangocms_versioning") + return None + + +@cache +def is_versioning_enabled() -> bool: from .models import AliasContent - try: - app_config = apps.get_app_config("djangocms_versioning") - return app_config.cms_extension.is_content_model_versioned(AliasContent) - except LookupError: - return False + for app_config in apps.get_app_configs(): + try: + print(app_config) + return app_config.cms_extension.is_content_model_versioned(AliasContent) + except AttributeError: + continue + return False def emit_content_change(objs, sender=None): From 7769cabe6ac5484eb03c48a6189f771d9fdc8fbc Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Wed, 4 Feb 2026 10:41:21 +0100 Subject: [PATCH 3/8] feat: Add compiled fr locale --- djangocms_alias/locale/fr/LC_MESSAGES/django.mo | Bin 0 -> 6031 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 djangocms_alias/locale/fr/LC_MESSAGES/django.mo diff --git a/djangocms_alias/locale/fr/LC_MESSAGES/django.mo b/djangocms_alias/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..7066d808907073022b2d4e222dbf34f97bb76ab6 GIT binary patch literal 6031 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 literal 0 HcmV?d00001 From 965effea738cdfcf679fbe3ba838917c39533ba9 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Wed, 4 Feb 2026 10:54:26 +0100 Subject: [PATCH 4/8] Apply suggestion from @fsbraun --- djangocms_alias/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/djangocms_alias/utils.py b/djangocms_alias/utils.py index 6822c52a..6e0c2c79 100644 --- a/djangocms_alias/utils.py +++ b/djangocms_alias/utils.py @@ -16,7 +16,6 @@ def is_versioning_enabled() -> bool: for app_config in apps.get_app_configs(): try: - print(app_config) return app_config.cms_extension.is_content_model_versioned(AliasContent) except AttributeError: continue From ced36b125281a0c4fcc3db371140b44588df199e Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Wed, 4 Feb 2026 10:59:02 +0100 Subject: [PATCH 5/8] Apply suggestion from @fsbraun --- djangocms_alias/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_alias/models.py b/djangocms_alias/models.py index 1d14f21e..fe2df3db 100644 --- a/djangocms_alias/models.py +++ b/djangocms_alias/models.py @@ -168,7 +168,7 @@ def get_name(self, language=None): if version.state == DRAFT: return f"{name} (Not published)" except (ImportError, ModuleNotFoundError, AttributeError): - pass + return name # djangocms versioning unreachable for draft check - just return the name return name def get_content(self, language=None, show_draft_content=False): From 0b07fd65c1217904b75e6307cd964035449bc1cf Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Wed, 4 Feb 2026 11:05:31 +0100 Subject: [PATCH 6/8] fix: Add missing super().__init__() --- djangocms_alias/cms_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/djangocms_alias/cms_config.py b/djangocms_alias/cms_config.py index f5902917..dbdc8a41 100644 --- a/djangocms_alias/cms_config.py +++ b/djangocms_alias/cms_config.py @@ -23,6 +23,7 @@ class AliasCMSConfig(CMSAppConfig): cms_wizards = [create_alias_wizard] def __init__(self, app_config): + super().__init__(app_config) VersionableItem = get_versionable_item(self) self.djangocms_moderation_enabled = getattr(settings, "MODERATING_ALIAS_MODELS_ENABLED", True) self.djangocms_versioning_enabled = getattr( From 1befa4cf6161151a9dd1156cc559540144a02d83 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Wed, 4 Feb 2026 11:55:50 +0100 Subject: [PATCH 7/8] fix: Simplify is_versioning_enabled() --- djangocms_alias/utils.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/djangocms_alias/utils.py b/djangocms_alias/utils.py index 6e0c2c79..0046123c 100644 --- a/djangocms_alias/utils.py +++ b/djangocms_alias/utils.py @@ -12,14 +12,12 @@ def get_versionable_item(cms_config) -> type | None: @cache def is_versioning_enabled() -> bool: - from .models import AliasContent - - for app_config in apps.get_app_configs(): - try: - return app_config.cms_extension.is_content_model_versioned(AliasContent) - except AttributeError: - continue - return False + """ + is_versioning_enabled returns True if djangocms-alias has registered itself + for verisoning + """ + cms_config = apps.get_app_config("djangocms_alias").cms_config + return hasattr(cms_config, "versioning") and bool(cms_config.versioning) def emit_content_change(objs, sender=None): From 9c88494733d1d66ff5fca65356eb1efa97d675d7 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Wed, 4 Feb 2026 11:56:44 +0100 Subject: [PATCH 8/8] even simpler --- djangocms_alias/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/djangocms_alias/utils.py b/djangocms_alias/utils.py index 0046123c..7ee161c9 100644 --- a/djangocms_alias/utils.py +++ b/djangocms_alias/utils.py @@ -10,14 +10,13 @@ def get_versionable_item(cms_config) -> type | None: return None -@cache def is_versioning_enabled() -> bool: """ is_versioning_enabled returns True if djangocms-alias has registered itself for verisoning """ cms_config = apps.get_app_config("djangocms_alias").cms_config - return hasattr(cms_config, "versioning") and bool(cms_config.versioning) + return bool(getattr(cms_config, "versioning", False)) def emit_content_change(objs, sender=None):