From e508cbc9c9944e9a4fef0cf262aa0d894a2b198c Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 28 Sep 2020 11:51:11 +0100 Subject: [PATCH] Allow ignoring a page when finding an available slug This is useful for when using this function to update a pages slug --- wagtail/core/tests/test_utils.py | 10 +++++++++- wagtail/core/utils.py | 17 +++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/wagtail/core/tests/test_utils.py b/wagtail/core/tests/test_utils.py index 8c130a2fb2..73ff0ae993 100644 --- a/wagtail/core/tests/test_utils.py +++ b/wagtail/core/tests/test_utils.py @@ -125,7 +125,9 @@ class TestFindAvailableSlug(TestCase): self.root_page = Page.objects.get(depth=1) self.home_page = Page.objects.get(depth=2) - self.root_page.add_child(instance=Page(title="Second homepage", slug="home-1")) + self.second_home_page = self.root_page.add_child( + instance=Page(title="Second homepage", slug="home-1") + ) def test_find_available_slug(self): with self.assertNumQueries(1): @@ -140,6 +142,12 @@ class TestFindAvailableSlug(TestCase): self.assertEqual(slug, "home-2") + def test_find_available_slug_ignore_page_id(self): + with self.assertNumQueries(1): + slug = find_available_slug(self.root_page, "home", ignore_page_id=self.second_home_page.id) + + self.assertEqual(slug, "home-1") + @override_settings( USE_I18N=True, diff --git a/wagtail/core/utils.py b/wagtail/core/utils.py index 181c8c9f37..e7de11415a 100644 --- a/wagtail/core/utils.py +++ b/wagtail/core/utils.py @@ -176,7 +176,7 @@ class InvokeViaAttributeShortcut: return method(name) -def find_available_slug(parent, requested_slug): +def find_available_slug(parent, requested_slug, ignore_page_id=None): """ Finds an available slug within the specified parent. @@ -187,12 +187,17 @@ def find_available_slug(parent, requested_slug): - 'requested-slug-2' And so on, until an available slug is found. + + The `ignore_page_id` keyword argument is useful for when you are updating a page, + you can pass the page being updated here so the page's current slug is not + treated as in use by another page. """ - existing_slugs = set( - parent.get_children() - .filter(slug__startswith=requested_slug) - .values_list("slug", flat=True) - ) + pages = parent.get_children().filter(slug__startswith=requested_slug) + + if ignore_page_id: + pages = pages.exclude(id=ignore_page_id) + + existing_slugs = set(pages.values_list("slug", flat=True)) slug = requested_slug number = 1