Skip to content

Commit

Permalink
feat: menu cloning
Browse files Browse the repository at this point in the history
  • Loading branch information
francesco-filicetti committed May 21, 2021
1 parent fb28a07 commit 9349ef2
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 2 deletions.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
django>=2.0,<4.0
git+https://github.com/UniversitaDellaCalabria/django-auto-serializer@dev
django-filter
django-nested-admin>=3.3.2
django-taggit
Expand Down
14 changes: 13 additions & 1 deletion src/cms/api/tests/test_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.test import Client, TestCase
from django.urls import reverse

from cms.menus.models import NavigationBar
from cms.menus.models import NavigationBar, NavigationBarItem
from cms.menus.tests import MenuUnitTest

from cms.contexts.tests import ContextUnitTest
Expand Down Expand Up @@ -61,6 +61,18 @@ def test_menu(self):
res = req.get(url, content_type='application/json',)
assert isinstance(res.json(), dict)

# CLONE
current_menus = NavigationBar.objects.all().count()
url = reverse('unicms_api:editorial-board-menu-clone', kwargs={'pk': menu.pk})
res = req.get(url, content_type='application/json',)
assert isinstance(res.json(), dict)
new_current_menus = NavigationBar.objects.all().count()
assert new_current_menus == current_menus + 1
source_items = NavigationBarItem.objects.filter(menu=menu)
new_menu = NavigationBar.objects.last()
dest_items = NavigationBarItem.objects.filter(menu=new_menu)
assert source_items.count() == dest_items.count()

# GET, patch, put, delete
url = reverse('unicms_api:editorial-board-menu', kwargs={'pk': menu.pk})

Expand Down
1 change: 1 addition & 0 deletions src/cms/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@
urlpatterns += path(f'{menu_prefix}/', menu.MenuList.as_view(), name='editorial-board-menus'),
urlpatterns += path(f'{menu_prefix}/<int:pk>/', menu.MenuView.as_view(), name='editorial-board-menu'),
urlpatterns += path(f'{menu_prefix}/<int:pk>/logs/', menu.MenuLogsView.as_view(), name='editorial-board-menu-logs'),
urlpatterns += path(f'{menu_prefix}/<int:pk>/clone/', menu.MenuCloneView.as_view(), name='editorial-board-menu-clone'),
urlpatterns += path(f'{menu_prefix}/form/', menu.MenuFormView.as_view(), name='editorial-board-menu-form'),

# menu items
Expand Down
41 changes: 40 additions & 1 deletion src/cms/api/views/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils import timezone
from django.utils.decorators import method_decorator

from rest_framework.exceptions import NotFound, PermissionDenied
Expand All @@ -11,13 +12,14 @@
from rest_framework.views import APIView

from cms.contexts.decorators import detect_language
from cms.contexts.utils import clone
from cms.menus.forms import MenuForm
from cms.menus.models import NavigationBar
from cms.menus.serializers import MenuSerializer

from . generics import UniCMSCachedRetrieveUpdateDestroyAPIView, UniCMSListCreateAPIView
from . logs import ObjectLogEntriesList
from .. exceptions import LoggedPermissionDenied
from .. exceptions import LoggedPermissionDenied, LoggedValidationException
from .. permissions import MenuGetCreatePermissions
from .. serializers import UniCMSFormSerializer
from .. utils import check_user_permission_on_object
Expand Down Expand Up @@ -170,3 +172,40 @@ def get_queryset(self, **kwargs):
item = get_object_or_404(NavigationBar, pk=object_id)
content_type_id = ContentType.objects.get_for_model(item).pk
return super().get_queryset(object_id, content_type_id)


class MenuCloneSchema(AutoSchema):
def get_operation_id(self, path, method):# pragma: no cover
return 'cloneMenu'


class MenuCloneView(APIView):

schema = MenuCloneSchema()
description = ""
permission_classes = [MenuGetCreatePermissions]
serializer_class = MenuSerializer

def get_queryset(self):
"""
"""
menu_id = self.kwargs['pk']
menus = NavigationBar.objects.filter(pk=menu_id)
return menus

def get(self, request, *args, **kwargs):
item = self.get_queryset().first()
if not item: raise Http404
try:
new_menu = clone(item,
excluded_fields=['created', 'modified'],
excluded_childrens=['pagemenu'],
custom_values={'name': f'{item.name} (copy {timezone.localtime()})'},
recursive_custom_values={'created_by': request.user,
'modified_by': None})
except Exception as e:
raise LoggedValidationException(classname=self.__class__.__name__,
resource=request.method,
detail=e)
result = self.serializer_class(new_menu)
return Response(result.data)
27 changes: 27 additions & 0 deletions src/cms/contexts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

from copy import deepcopy

from django_auto_serializer.auto_serializer import *


logger = logging.getLogger(__name__)
CMS_PATH_PREFIX = getattr(settings, 'CMS_PATH_PREFIX', '')
Expand Down Expand Up @@ -176,3 +178,28 @@ def log_obj_event(user, obj, data={}, action_flag=CHANGE):
object_repr = obj.__str__(),
action_flag = action_flag,
change_message = f'{msg}: {data}' or msg)


def clone(obj,
excluded_fields=[],
excluded_childrens=[],
custom_values={},
recursive_custom_values={}):
"""
clone object using django_auto_serializer
"""
try:
si = SerializableInstance(obj,
excluded_fields=excluded_fields,
excluded_childrens=excluded_childrens,
auto_fields = False,
change_uniques = True,
duplicate = True)
si.serialize_tree()
si.remove_duplicates()
isi = ImportableSerializedInstance(si.dict)
new_obj = isi.save(custom_values=custom_values,
recursive_custom_values=recursive_custom_values)
return new_obj
except Exception as e:
raise e
5 changes: 5 additions & 0 deletions src/cms/templates/templatetags/unicms_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ def settings_value(name, **kwargs):
value = getattr(settings, name, None)
if value and kwargs: return value.format(**kwargs)
return value


@register.simple_tag
def installed_app(app_name):
return app_name in settings.INSTALLED_APPS

0 comments on commit 9349ef2

Please sign in to comment.