Repository: wagtail/wagtail

Issue:
Child url not properly updated when parent slug changes
I have a page with "category-one" slug and a child page with "article-3" slug. The child url is "/category-one/article-3". If I change the parent page's slug to "category-onefds" the child url returns "/category-onefds/ds/article-3/" as a url. This value appears in the DB (url_path in wagtailcore_page table)

If I edit the child page and "publish" it without even doing any changes the url path gets the right value.



Discussion:

Resolving patch:
diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py
--- a/wagtail/wagtailcore/models.py
+++ b/wagtail/wagtailcore/models.py
@@ -337,14 +337,17 @@ def save(self, *args, **kwargs):
             # has been set and so we can safely call get_parent
             self.set_url_path(self.get_parent())
         else:
-            # see if the slug has changed from the record in the db, in which case we need to
-            # update url_path of self and all descendants
-            old_record = Page.objects.get(id=self.id)
-            if old_record.slug != self.slug:
-                self.set_url_path(self.get_parent())
-                update_descendant_url_paths = True
-                old_url_path = old_record.url_path
-                new_url_path = self.url_path
+            # Check that we are committing the slug to the database
+            # Basically: If update_fields has been specified, and slug is not included, skip this step
+            if not ('update_fields' in kwargs and 'slug' not in kwargs['update_fields']):
+                # see if the slug has changed from the record in the db, in which case we need to
+                # update url_path of self and all descendants
+                old_record = Page.objects.get(id=self.id)
+                if old_record.slug != self.slug:
+                    self.set_url_path(self.get_parent())
+                    update_descendant_url_paths = True
+                    old_url_path = old_record.url_path
+                    new_url_path = self.url_path
 
         result = super(Page, self).save(*args, **kwargs)
 


Test patch:
diff --git a/wagtail/wagtailcore/tests/test_page_model.py b/wagtail/wagtailcore/tests/test_page_model.py
--- a/wagtail/wagtailcore/tests/test_page_model.py
+++ b/wagtail/wagtailcore/tests/test_page_model.py
@@ -600,3 +600,23 @@ def test_allowed_parent_page_types(self):
         # BusinessSubIndex only allows BusinessIndex as a parent
         self.assertNotIn(ContentType.objects.get_for_model(SimplePage), BusinessSubIndex.allowed_parent_page_types())
         self.assertIn(ContentType.objects.get_for_model(BusinessIndex), BusinessSubIndex.allowed_parent_page_types())
+
+
+class TestIssue735(TestCase):
+    """
+    Issue 735 reports that URL paths of child pages are not
+    updated correctly when slugs of parent pages are updated
+    """
+    fixtures = ['test.json']
+
+    def test_child_urls_updated_on_parent_publish(self):
+        event_index = Page.objects.get(url_path='/home/events/')
+        christmas_event = EventPage.objects.get(url_path='/home/events/christmas/')
+
+        # Change the event index slug and publish it
+        event_index.slug = 'old-events'
+        event_index.save_revision().publish()
+
+        # Check that the christmas events url path updated correctly
+        new_christmas_event = EventPage.objects.get(id=christmas_event.id)
+        self.assertEqual(new_christmas_event.url_path, '/home/old-events/christmas/')