Skip to content

Commit

Permalink
fix: auto-create static alias content in current language (#165)
Browse files Browse the repository at this point in the history
  • Loading branch information
fsbraun authored Apr 1, 2023
1 parent 7525409 commit 08ec77b
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 68 deletions.
6 changes: 1 addition & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,10 @@ repos:
hooks:
- id: flake8
additional_dependencies:
# - flake8-broken-line
- flake8-bugbear
- flake8-builtins
- flake8-coding
- flake8-commas
- flake8-comprehensions
- flake8-eradicate
- flake8-quotes
# - flake8-eradicate
- flake8-tidy-imports
- pep8-naming

Expand Down
2 changes: 0 additions & 2 deletions djangocms_alias/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
__version__ = '1.11.0'

default_app_config = 'djangocms_alias.apps.AliasConfig'
7 changes: 4 additions & 3 deletions djangocms_alias/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,13 @@ def get_queryset(self, request):
return queryset

# Add Alias category in the admin manager list and order field
@admin.display(
description=_('category'),
ordering="alias_category_translations_ordered",
)
def get_category(self, obj):
return obj.alias.category

get_category.short_description = _('category')
get_category.admin_order_field = "alias_category_translations_ordered"

def has_add_permission(self, request, obj=None):
# FIXME: It is not currently possible to add an alias from the django admin changelist issue #97
# https://github.com/django-cms/djangocms-alias/issues/97
Expand Down
2 changes: 1 addition & 1 deletion djangocms_alias/cms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def get_render_template(self, context, instance, placeholder):
and instance.is_recursive()
):
return 'djangocms_alias/alias_recursive.html'
return 'djangocms_alias/{}/alias.html'.format(instance.template)
return f'djangocms_alias/{instance.template}/alias.html'

@classmethod
def get_extra_plugin_menu_items(cls, request, plugin):
Expand Down
6 changes: 3 additions & 3 deletions djangocms_alias/cms_toolbars.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def change_language_menu(self):

if add:
add_plugins_menu = language_menu.get_or_create_menu(
'{0}-add'.format(LANGUAGE_MENU_IDENTIFIER),
f'{LANGUAGE_MENU_IDENTIFIER}-add',
_('Add Translation'),
)
add_url = admin_reverse('djangocms_alias_aliascontent_add')
Expand All @@ -238,7 +238,7 @@ def change_language_menu(self):

if remove:
remove_plugins_menu = language_menu.get_or_create_menu(
'{0}-del'.format(LANGUAGE_MENU_IDENTIFIER),
f'{LANGUAGE_MENU_IDENTIFIER}-del',
_('Delete Translation'),
)
disabled = len(remove) == 1
Expand All @@ -256,7 +256,7 @@ def change_language_menu(self):

if copy:
copy_plugins_menu = language_menu.get_or_create_menu(
'{0}-copy'.format(LANGUAGE_MENU_IDENTIFIER),
f'{LANGUAGE_MENU_IDENTIFIER}-copy',
_('Copy all plugins')
)
title = _('from %s')
Expand Down
8 changes: 4 additions & 4 deletions djangocms_alias/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def objects_using(self):
if obj_class_name.endswith('Content'):
attr_name = obj_class_name.replace('Content', '').lower()
attr_related_model = obj._meta.get_field(attr_name).related_model
id_attr = getattr(obj, '{}_id'.format(attr_name))
id_attr = getattr(obj, f'{attr_name}_id')
if id_attr:
object_ids[attr_related_model].update([id_attr])
else:
Expand All @@ -150,13 +150,13 @@ def objects_using(self):

def get_name(self, language=None):
content = self.get_content(language, show_draft_content=True)
name = getattr(content, 'name', 'Alias {} (No content)'.format(self.pk))
name = getattr(content, 'name', f'Alias {self.pk} (No content)')
if is_versioning_enabled() and content:
from djangocms_versioning.constants import DRAFT
version = content.versions.first()

if version.state == DRAFT:
return '{} (Not published)'.format(name)
return f'{name} (Not published)'

return name

Expand Down Expand Up @@ -282,7 +282,7 @@ class Meta:
verbose_name_plural = _('alias contents')

def __str__(self):
return '{} ({})'.format(self.name, self.language)
return f'{self.name} ({self.language})'

@cached_property
def placeholder(self):
Expand Down
20 changes: 17 additions & 3 deletions djangocms_alias/templatetags/djangocms_alias_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from cms.templatetags.cms_tags import PlaceholderOptions
from cms.toolbar.utils import get_toolbar_from_request
from cms.utils import get_current_site, get_language_from_request
from cms.utils.i18n import get_default_language_for_site
from cms.utils.i18n import get_language_list
from cms.utils.placeholder import validate_placeholder_name
from cms.utils.urlutils import add_url_parameters, admin_reverse

Expand Down Expand Up @@ -86,16 +86,22 @@ def _get_alias(self, request, static_code, extra_bits):
else:
alias_filter_kwargs['site_id__isnull'] = True

if hasattr(request, "toolbar"):
# Try getting language from the toolbar first (end and view endpoints)
language = getattr(request.toolbar.get_object(), "language", None)
if language not in get_language_list(current_site):
language = None
else:
language = get_language_from_request(request)
# Try and find an Alias to render
alias = Alias.objects.filter(**alias_filter_kwargs).first()
# If there is no alias found we need to create one
if not alias:

# If versioning is enabled we can only create the records with a logged in user / staff member
# If versioning is enabled we can only create the records with a logged-in user / staff member
if is_versioning_enabled() and not request.user.is_authenticated:
return None

language = get_default_language_for_site(current_site)
# Parlers get_or_create doesn't work well with translations, so we must perform our own get or create
default_category = Category.objects.filter(translations__name=DEFAULT_STATIC_ALIAS_CATEGORY_NAME).first()
if not default_category:
Expand All @@ -110,6 +116,13 @@ def _get_alias(self, request, static_code, extra_bits):
alias_creation_kwargs['site'] = current_site

alias = Alias.objects.create(category=default_category, **alias_creation_kwargs)

if not AliasContent._default_manager.filter(alias=alias, language=language).exists():
# Create a first content object if none exists in the given language.
# If versioning is enabled we can only create the records with a logged-in user / staff member
if is_versioning_enabled() and not request.user.is_authenticated:
return None

alias_content = AliasContent.objects.create(
alias=alias,
name=static_code,
Expand All @@ -120,6 +133,7 @@ def _get_alias(self, request, static_code, extra_bits):
from djangocms_versioning.models import Version

Version.objects.create(content=alias_content, created_by=request.user)
alias._content_cache[language] = alias_content

return alias

Expand Down
26 changes: 13 additions & 13 deletions djangocms_alias/urls.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
from django.urls import re_path
from django.urls import path


from . import constants, views # isort:skip


urlpatterns = [
re_path(
r'^create-alias/$',
path(
'create-alias/',
views.create_alias_view,
name=constants.CREATE_ALIAS_URL_NAME,
),
re_path(
r'^aliases/(?P<pk>\d+)/usage/$',
path(
'aliases/<int:pk>/usage/',
views.alias_usage_view,
name=constants.USAGE_ALIAS_URL_NAME,
),
re_path(
r'^detach-alias/(?P<plugin_pk>\d+)/$',
path(
'detach-alias/<int:plugin_pk>/',
views.detach_alias_plugin_view,
name=constants.DETACH_ALIAS_PLUGIN_URL_NAME,
),
re_path(
r'^delete-alias/(?P<pk>\d+)/$',
path(
'delete-alias/<int:pk>/',
views.delete_alias_view,
name=constants.DELETE_ALIAS_URL_NAME,
),
re_path(
r'^select2/$',
path(
'select2/',
views.AliasSelect2View.as_view(),
name=constants.SELECT2_ALIAS_URL_NAME,
),
re_path(
r'^category-select2/$',
path(
'category-select2/',
views.CategorySelect2View.as_view(),
name=constants.CATEGORY_SELECT2_URL_NAME,
),
Expand Down
4 changes: 2 additions & 2 deletions djangocms_alias/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def delete_alias_view(request, pk, *args, **kwargs):
model=AliasModel,
admin_site=admin.site,
)
response = alias_admin.delete_view(request, pk)
response = alias_admin.delete_view(request, str(pk))
if request.POST and response.status_code in [200, 302]:
return HttpResponse(JAVASCRIPT_SUCCESS_RESPONSE)
return response
Expand Down Expand Up @@ -294,7 +294,7 @@ def alias_usage_view(request, pk):

alias = get_object_or_404(AliasModel.objects.all(), pk=pk)
opts = Alias.model._meta
title = _('Objects using alias: {}'.format(alias))
title = _(f'Objects using alias: {alias}')
context = {
'has_change_permission': True,
'opts': opts,
Expand Down
40 changes: 20 additions & 20 deletions tests/test_admin_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,19 @@ def test_language_filter(self):

self.assertEqual(
set(response_default.context["cl"].queryset),
set([expected_en_content])
{expected_en_content}
)
self.assertEqual(
set(response_en.context["cl"].queryset),
set([expected_en_content])
{expected_en_content}
)
self.assertEqual(
set(response_de.context["cl"].queryset),
set([expected_de_content])
{expected_de_content}
)
self.assertEqual(
set(response_fr.context["cl"].queryset),
set([])
set()
)


Expand Down Expand Up @@ -145,31 +145,31 @@ def test_site_filter(self):
# 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])
{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])
{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_site_alias_content}
)
# No are shown when filtered by an empty site
self.assertEqual(
set(response_empty_site.context["cl"].queryset),
set([])
set()
)


Expand Down Expand Up @@ -216,9 +216,9 @@ def test_unpublished_filter(self):
# filter by unpublished show

# show all alias contents excluding unpublished versions
self.assertEqual(set(qs_default), set([expected_en_content]))
self.assertEqual(set(qs_default), {expected_en_content})
# show all aliase contents including unpublished versions
self.assertEqual(set(qs_unpublished), set([expected_unpublished]))
self.assertEqual(set(qs_unpublished), {expected_unpublished})


class CatergoryFiltersTestCase(BaseAliasPluginTestCase):
Expand Down Expand Up @@ -261,20 +261,20 @@ def test_category_filter_no_verisoning(self):
# By default all alias contents are shown
self.assertEqual(
set(response_default.context["cl"].queryset),
set([
{
expected_category_one_content,
expected_category_two_content,
])
}
)
# show alias contents filter by category one
self.assertEqual(
set(category_one_filter_response.context["cl"].queryset),
set([expected_category_one_content])
{expected_category_one_content}
)
# show alias contents filter by category two
self.assertEqual(
set(category_two_filter_response.context["cl"].queryset),
set([expected_category_two_content])
{expected_category_two_content}
)

@skipUnless(is_versioning_enabled(), 'Test only relevant when versioning enabled')
Expand Down Expand Up @@ -319,20 +319,20 @@ def test_category_filter_with_verisoning(self):
# By default all alias contents are shown
self.assertEqual(
set(response_default.context["cl"].queryset),
set([
{
expected_category_one_content,
expected_category_two_content,
])
}
)
# show alias contents filter by category one
self.assertEqual(
set(category_one_filter_response.context["cl"].queryset),
set([expected_category_one_content])
{expected_category_one_content}
)
# show alias contents filter by category two
self.assertEqual(
set(category_two_filter_response.context["cl"].queryset),
set([expected_category_two_content])
{expected_category_two_content}
)

def test_category_filter_lookups_ordered_alphabetical(self):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_cms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_extra_plugin_items_for_regular_plugins(self):
self.assertEqual(extra_item.action, 'modal')
parsed_url = urlparse(extra_item.url)
self.assertEqual(parsed_url.path, self.get_create_alias_endpoint())
self.assertIn('plugin={}'.format(self.plugin.pk), parsed_url.query)
self.assertIn(f'plugin={self.plugin.pk}', parsed_url.query)

def test_extra_plugin_items_for_alias_plugins(self):
alias = self._create_alias()
Expand Down Expand Up @@ -73,7 +73,7 @@ def test_extra_plugin_items_for_placeholder(self):
parsed_url = urlparse(extra_item.url)
self.assertEqual(parsed_url.path, self.get_create_alias_endpoint())
self.assertIn(
'placeholder={}'.format(self.placeholder.pk),
f'placeholder={self.placeholder.pk}',
parsed_url.query,
)

Expand Down
Loading

0 comments on commit 08ec77b

Please sign in to comment.