diff --git a/combo/manager/views.py b/combo/manager/views.py index 9d211846..6b051ba1 100644 --- a/combo/manager/views.py +++ b/combo/manager/views.py @@ -460,9 +460,18 @@ def cell_order(request, page_pk): def page_order(request): new_order = [int(x) for x in request.GET['new-order'].split(',')] moved_page = Page.objects.get(id=request.GET['moved-page-id']) - current_parent_id = moved_page.parent_id if request.GET['moved-page-new-parent']: - moved_page.parent_id = request.GET['moved-page-new-parent'] + # recreate full hierarchy to avoid cycles + current_hierarchy = Page.objects.get(id=request.GET['moved-page-new-parent']).get_parents_and_self() + new_hierarchy = [x for x in current_hierarchy if not x.id == moved_page.id] + [moved_page] + for i, page in enumerate(new_hierarchy): + old_parent_id = page.parent_id + if i == 0: + page.parent_id = None + else: + page.parent_id = new_hierarchy[i-1].id + if old_parent_id != page.parent_id: + page.save() else: moved_page.parent_id = None moved_page.save() diff --git a/tests/test_manager.py b/tests/test_manager.py index f9426f72..f60f386d 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -277,6 +277,37 @@ def test_page_reorder(app, admin_user): 'new-order': ','.join([str(x) for x in [page1.id, page2.id, page4.id, page3.id]])}) assert Page.objects.get(id=page4.id).slug.startswith('three-') + # move a parent page as a child of its own child + for page in (page1, page2, page3, page4): + page.parent = None + page.save() + page2.parent = page1 + page2.save() + page3.parent = page2 + page3.save() + resp = app.get('/manage/pages/order', params={ + 'moved-page-id': page1.id, + 'moved-page-new-parent': page3.id, + 'new-order': ','.join([str(x) for x in [page2.id, page3.id, page1.id, page4.id]])}) + assert Page.objects.get(id=page2.id).parent_id is None + + for page in (page1, page2, page3, page4): + page.parent = None + page.save() + page2.parent = page1 + page2.save() + page3.parent = page2 + page3.save() + page4.parent = page3 + page4.save() + resp = app.get('/manage/pages/order', params={ + 'moved-page-id': page2.id, + 'moved-page-new-parent': page4.id, + 'new-order': ','.join([str(x) for x in [page1.id, page3.id, page4.id, page2.id]])}) + assert Page.objects.get(id=page1.id).parent_id is None + assert Page.objects.get(id=page3.id).parent_id == page1.id + + def test_export_page(app, admin_user): Page.objects.all().delete() page = Page(title='One', slug='one', template_name='standard')