diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b7e5e26c..68c8c193 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,7 @@ Changelog Unreleased ========== +* feat: Add AliasContent admin changelist Site filter 1.3.0 (2022-04-12) ================== diff --git a/djangocms_alias/admin.py b/djangocms_alias/admin.py index 57c9dd88..631ac9e0 100644 --- a/djangocms_alias/admin.py +++ b/djangocms_alias/admin.py @@ -9,7 +9,7 @@ from .cms_config import AliasCMSConfig from .constants import USAGE_ALIAS_URL_NAME -from .filters import LanguageFilter +from .filters import LanguageFilter, SiteFilter from .forms import AliasContentForm from .models import Alias, AliasContent, Category from .urls import urlpatterns @@ -101,7 +101,7 @@ def delete_model(self, request, obj): @admin.register(AliasContent) class AliasContentAdmin(*alias_content_admin_classes): form = AliasContentForm - list_filter = (LanguageFilter,) + list_filter = (LanguageFilter, SiteFilter) list_display = alias_content_admin_list_display # Disable dropdown actions actions = None diff --git a/djangocms_alias/constants.py b/djangocms_alias/constants.py index e6b13dac..5119b98b 100644 --- a/djangocms_alias/constants.py +++ b/djangocms_alias/constants.py @@ -1,5 +1,6 @@ PLUGIN_URL_NAME_PREFIX = 'djangocms_alias' +# Alias Url endpoint names CREATE_ALIAS_URL_NAME = f'{PLUGIN_URL_NAME_PREFIX}_create' DELETE_ALIAS_URL_NAME = f'{PLUGIN_URL_NAME_PREFIX}_delete' DETACH_ALIAS_PLUGIN_URL_NAME = f'{PLUGIN_URL_NAME_PREFIX}_detach_plugin' @@ -10,4 +11,10 @@ USAGE_ALIAS_URL_NAME = f'{PLUGIN_URL_NAME_PREFIX}_alias_usage' LIST_ALIAS_URL_NAME = f'{PLUGIN_URL_NAME_PREFIX}_aliascontent_changelist' +# Static Alias DEFAULT_STATIC_ALIAS_CATEGORY_NAME = "Static Alias" + +# Admin Filters +LANGUAGE_FILTER_URL_PARAM = "language" +SITE_FILTER_URL_PARAM = "site" +SITE_FILTER_NO_SITE_VALUE = "no_site" diff --git a/djangocms_alias/filters.py b/djangocms_alias/filters.py index 8071eee0..356c0c89 100644 --- a/djangocms_alias/filters.py +++ b/djangocms_alias/filters.py @@ -1,12 +1,19 @@ from django.contrib import admin from django.utils.translation import gettext_lazy as _ +from cms.forms.utils import get_sites from cms.utils.i18n import get_language_tuple, get_site_language_from_request +from .constants import ( + LANGUAGE_FILTER_URL_PARAM, + SITE_FILTER_NO_SITE_VALUE, + SITE_FILTER_URL_PARAM, +) + class LanguageFilter(admin.SimpleListFilter): - title = _("language") - parameter_name = "language" + title = _("Language") + parameter_name = LANGUAGE_FILTER_URL_PARAM def lookups(self, request, model_admin): return get_language_tuple() @@ -31,3 +38,41 @@ def choices(self, changelist): ), "display": title, } + + +class SiteFilter(admin.SimpleListFilter): + title = _("Site") + parameter_name = SITE_FILTER_URL_PARAM + + def lookups(self, request, model_admin): + return [(site.pk, site.name) for site in get_sites()] + + def queryset(self, request, queryset): + chosen_site = self.value() + if chosen_site and chosen_site == SITE_FILTER_NO_SITE_VALUE: + return queryset.filter(alias__site__isnull=True) + elif chosen_site: + return queryset.filter(alias__site__pk=int(chosen_site)) + return queryset + + def choices(self, changelist): + yield { + "selected": self.value() is None, + "query_string": changelist.get_query_string(remove=[self.parameter_name]), + "display": _("All"), + } + yield { + "selected": self.value() == SITE_FILTER_NO_SITE_VALUE, + "query_string": changelist.get_query_string( + {self.parameter_name: SITE_FILTER_NO_SITE_VALUE} + ), + "display": _("No site"), + } + for lookup, title in self.lookup_choices: + yield { + "selected": self.value() == str(lookup), + "query_string": changelist.get_query_string( + {self.parameter_name: lookup} + ), + "display": title, + } diff --git a/tests/base.py b/tests/base.py index 1535a550..6584f0cc 100644 --- a/tests/base.py +++ b/tests/base.py @@ -181,8 +181,8 @@ def _get_instance_request(self, instance, user, path=None, edit=False, return request def _process_request_by_toolbar_middleware(self, request, obj=None): - midleware = ToolbarMiddleware() - midleware.process_request(request) + middleware = ToolbarMiddleware(request) + middleware.process_request(request) if hasattr(request, 'toolbar'): if obj: request.toolbar.set_object(obj) diff --git a/tests/test_admin.py b/tests/test_admin.py index 36697103..26c71a64 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -11,58 +11,6 @@ from djangocms_alias.utils import is_versioning_enabled -class FiltersTestCase(CMSTestCase): - def setUp(self): - self.superuser = self.get_superuser() - - def test_language_filter(self): - """ - When rendering aliascontent manager language filter - """ - category = Category.objects.create(name='Language Filter Category') - alias = AliasModel.objects.create( - category=category, - position=0, - ) - expected_en_content = AliasContent.objects.create( - alias=alias, - name="EN Alias Content", - language="en", - ) - expected_de_content = AliasContent.objects.create( - alias=alias, - name="DE Alias Content", - language="de", - ) - # If versioning is enabled be sure to create a version - if is_versioning_enabled(): - from djangocms_versioning.models import Version - - Version.objects.create(content=expected_en_content, created_by=self.superuser) - Version.objects.create(content=expected_de_content, created_by=self.superuser) - - base_url = self.get_admin_url(AliasContent, "changelist") - - with self.login_user_context(self.superuser): - # en is the default language configured for the site - response_default = self.client.get(base_url) - qs_default = response_default.context["cl"].queryset - # en should have a result - response_en = self.client.get(base_url + "?language=en") - qs_en = response_en.context["cl"].queryset - # de should have a result - response_de = self.client.get(base_url + "?language=de") - qs_de = response_de.context["cl"].queryset - # fr should have no result and be empty because nothing was created - response_fr = self.client.get(base_url + "?language=fr") - qs_fr = response_fr.context["cl"].queryset - - self.assertEqual(set(qs_default), set([expected_en_content])) - self.assertEqual(set(qs_en), set([expected_en_content])) - self.assertEqual(set(qs_de), set([expected_de_content])) - self.assertEqual(set(qs_fr), set([])) - - class AliasContentManagerTestCase(CMSTestCase): def setUp(self): self.superuser = self.get_superuser() diff --git a/tests/test_admin_filters.py b/tests/test_admin_filters.py new file mode 100644 index 00000000..894603c3 --- /dev/null +++ b/tests/test_admin_filters.py @@ -0,0 +1,168 @@ +from django.contrib.sites.models import Site + +from cms.utils import get_current_site + +from djangocms_alias.constants import ( + SITE_FILTER_NO_SITE_VALUE, + SITE_FILTER_URL_PARAM, +) +from djangocms_alias.models import Alias as AliasModel, AliasContent, Category +from djangocms_alias.utils import is_versioning_enabled + +from .base import BaseAliasPluginTestCase + + +class LanguageFiltersTestCase(BaseAliasPluginTestCase): + + def test_language_filter(self): + """ + When rendering aliascontent manager language filter changing the language + should filter the results. + """ + category = Category.objects.create(name='Language Filter Category') + alias = AliasModel.objects.create( + category=category, + position=0, + ) + expected_en_content = AliasContent.objects.create( + alias=alias, + name="EN Alias Content", + language="en", + ) + expected_de_content = AliasContent.objects.create( + alias=alias, + name="DE Alias Content", + language="de", + ) + # If versioning is enabled be sure to create a version + if is_versioning_enabled(): + from djangocms_versioning.models import Version + + Version.objects.create(content=expected_en_content, created_by=self.superuser) + Version.objects.create(content=expected_de_content, created_by=self.superuser) + + base_url = self.get_admin_url(AliasContent, "changelist") + + with self.login_user_context(self.superuser): + # en is the default language configured for the site + response_default = self.client.get(base_url) + # en should have a result + response_en = self.client.get(base_url + "?language=en") + # de should have a result + response_de = self.client.get(base_url + "?language=de") + # fr should have no result and be empty because nothing was created + response_fr = self.client.get(base_url + "?language=fr") + + self.assertEqual( + set(response_default.context["cl"].queryset), + set([expected_en_content]) + ) + self.assertEqual( + set(response_en.context["cl"].queryset), + set([expected_en_content]) + ) + self.assertEqual( + set(response_de.context["cl"].queryset), + set([expected_de_content]) + ) + self.assertEqual( + set(response_fr.context["cl"].queryset), + set([]) + ) + + +class SiteFiltersTestCase(BaseAliasPluginTestCase): + + def test_site_filter(self): + """ + When rendering aliascontent manager site filter changing the site + should filter the results. + """ + current_site = get_current_site() + another_site = Site.objects.create( + name="Other site", + domain="othersite.here" + ) + empty_site = Site.objects.create( + name="Empty site", + domain="emptysite.here" + ) + category = Category.objects.create(name='Site Filter Category') + current_site_alias = AliasModel.objects.create( + category=category, + site=current_site, + ) + current_site_alias_content = AliasContent.objects.create( + alias=current_site_alias, + name="Current Site Alias Content", + language="en", + ) + another_site_alias = AliasModel.objects.create( + category=category, + site=another_site, + ) + another_site_alias_content = AliasContent.objects.create( + alias=another_site_alias, + name="Another Site Alias Content", + language="en", + ) + no_site_alias = AliasModel.objects.create( + category=category, + ) + no_site_alias_content = AliasContent.objects.create( + alias=no_site_alias, + name="No Site Alias Content", + language="en", + ) + + # If versioning is enabled be sure to create a version + if is_versioning_enabled(): + from djangocms_versioning.models import Version + + Version.objects.create(content=current_site_alias_content, created_by=self.superuser) + Version.objects.create(content=another_site_alias_content, created_by=self.superuser) + Version.objects.create(content=no_site_alias_content, created_by=self.superuser) + + base_url = self.get_admin_url(AliasContent, "changelist") + + with self.login_user_context(self.superuser): + # en is the default language configured for the site + response_default = self.client.get(base_url) + # filter by aliases with the current site + response_current_site = self.client.get(f"{base_url}?{SITE_FILTER_URL_PARAM}={current_site.pk}") + # filter by aliases with a different site set + response_other_site = self.client.get(f"{base_url}?{SITE_FILTER_URL_PARAM}={another_site.pk}") + # filter by aliases with an empty site set + response_empty_site = self.client.get(f"{base_url}?{SITE_FILTER_URL_PARAM}={empty_site.pk}") + # filter by aliases with no site set + response_no_site = self.client.get(f"{base_url}?{SITE_FILTER_URL_PARAM}={SITE_FILTER_NO_SITE_VALUE}") + + # By default all alias are shown + self.assertEqual( + set(response_default.context["cl"].queryset), + set([ + current_site_alias_content, + another_site_alias_content, + no_site_alias_content, + ]) + ) + # Only alias attached to the current site are shown when filtered by the current site + self.assertEqual( + set(response_current_site.context["cl"].queryset), + set([current_site_alias_content]) + ) + # Only alias attached to the current site are shown when filtered by another site + self.assertEqual( + set(response_other_site.context["cl"].queryset), + set([another_site_alias_content]) + ) + # Only alias attached to the current site are shown when filtered by no site + self.assertEqual( + set(response_no_site.context["cl"].queryset), + set([no_site_alias_content]) + ) + # No are shown when filtered by an empty site + self.assertEqual( + set(response_empty_site.context["cl"].queryset), + set([]) + )