Repository: django-cms/django-cms

Issue:
When Moving page to root position (topmost) old root throws 404 (CMS 3.0)
When I move a page from anywhere in the tree to the topmost position in the tree (root), the page that was previously in the root position will now throw a 404 when visited. This is due to the fact that the path field on the title of the page that got moved is not being recalculated.



Discussion:

Resolving patch:
diff --git a/cms/models/pagemodel.py b/cms/models/pagemodel.py
--- a/cms/models/pagemodel.py
+++ b/cms/models/pagemodel.py
@@ -138,12 +138,13 @@ def move_page(self, target, position='first-child'):
         # do not mark the page as dirty after page moves
         self._publisher_keep_state = True
 
+        # readability counts :)
+        is_inherited_template = self.template == constants.TEMPLATE_INHERITANCE_MAGIC
+
         # make sure move_page does not break when using INHERIT template
         # and moving to a top level position
 
-        if (position in ('left', 'right')
-        and not target.parent
-        and self.template == constants.TEMPLATE_INHERITANCE_MAGIC):
+        if (position in ('left', 'right') and not target.parent and is_inherited_template):
             self.template = self.get_template()
         self.move_to(target, position)
 
@@ -154,6 +155,8 @@ def move_page(self, target, position='first-child'):
         self.save()  # always save the page after move, because of publisher
         # check the slugs
         page_utils.check_title_slugs(self)
+        # Make sure to update the slug and path of the target page.
+        page_utils.check_title_slugs(target)
 
         if self.publisher_public_id:
             # Ensure we have up to date mptt properties
diff --git a/cms/utils/page.py b/cms/utils/page.py
--- a/cms/utils/page.py
+++ b/cms/utils/page.py
@@ -80,7 +80,7 @@ def check_title_slugs(page):
     cut/paste.
     """
     for title in page.title_set.all():
-        old_slug = title.slug
+        old_slug, old_path = title.slug, title.path
         title.slug = get_available_slug(title)
-        if title.slug != old_slug:
+        if title.slug != old_slug or title.path != old_path:
             title.save()


Test patch:
diff --git a/cms/tests/page.py b/cms/tests/page.py
--- a/cms/tests/page.py
+++ b/cms/tests/page.py
@@ -351,16 +351,17 @@ def test_move_page(self):
             public_page3 = page3.publisher_public
             self.assertEqual(public_page3.get_absolute_url(),
                              self.get_pages_root() + page_data2['slug'] + "/" + page_data3['slug'] + "/")
-            # move page2 back to root and check path of 2 and 3
+            # set page2 as root and check path of 1 and 3
             response = self.client.post("/en/admin/cms/page/%s/move-page/" % page2.pk,
-                                        {"target": page1.pk, "position": "right"})
+                                        {"target": page1.pk, "position": "left"})
             self.assertEqual(response.status_code, 200)
             page1 = Page.objects.get(pk=page1.pk)
-            self.assertEqual(page1.get_path(), '')
+            self.assertEqual(page1.get_path(), page_data1['slug'])
             page2 = Page.objects.get(pk=page2.pk)
-            self.assertEqual(page2.get_path(), page_data2['slug'])
+            # Check that page2 is now at the root of the tree
+            self.assertEqual(page2.get_path(), '')
             page3 = Page.objects.get(pk=page3.pk)
-            self.assertEqual(page3.get_path(), page_data2['slug'] + "/" + page_data3['slug'])
+            self.assertEqual(page3.get_path(), page_data3['slug'])
 
     def test_move_page_inherit(self):
         parent = create_page("Parent", 'col_three.html', "en")