From a6036a33b14fc0c5cf29d227abad6388e07a0b7e Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Thu, 6 Jan 2022 16:53:34 +0100 Subject: [PATCH 2/2] data: fix get_by_natural_key for page (#60018) --- combo/data/models.py | 2 +- combo/data/query.py | 11 +++++++++++ tests/test_import_export.py | 14 ++++++++++++++ tests/test_manager.py | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/combo/data/models.py b/combo/data/models.py index 8841e4da..48e8b082 100644 --- a/combo/data/models.py +++ b/combo/data/models.py @@ -161,7 +161,7 @@ class PageManager(TreeManager): def get_by_natural_key(self, path): parts = [x for x in path.strip('/').split('/') if x] or ['index'] - return self.get(slug=parts[-1]) + return self.get_from_hierarchy(page_slugs=parts) def get_queryset(self): queryset = super().get_queryset() diff --git a/combo/data/query.py b/combo/data/query.py index cc5049b8..d25ccb2d 100644 --- a/combo/data/query.py +++ b/combo/data/query.py @@ -58,12 +58,14 @@ class TreeCompiler(SQLCompiler): WITH RECURSIVE __tree ( "tree_depth", "tree_path", + "tree_path_slugs", "tree_ordering", "tree_pk" ) AS ( SELECT 0 AS tree_depth, array[T.id] AS tree_path, + array[T.slug]::varchar(50)[] AS tree_path_slugs, array["order"] AS tree_ordering, T.id FROM data_page T @@ -74,6 +76,7 @@ class TreeCompiler(SQLCompiler): SELECT __tree.tree_depth + 1 AS tree_depth, __tree.tree_path || T.id, + (__tree.tree_path_slugs || T.slug)::varchar(50)[], __tree.tree_ordering || "order", T.id FROM data_page T @@ -87,6 +90,7 @@ class TreeCompiler(SQLCompiler): select={ 'tree_depth': '__tree.tree_depth', 'tree_path': '__tree.tree_path', + 'tree_path_slugs': '__tree.tree_path_slugs', 'tree_ordering': '__tree.tree_ordering', }, select_params=None, @@ -121,5 +125,12 @@ class TreeQuerySet(models.QuerySet): return queryset.exclude(pk=page.pk) return queryset + def get_from_hierarchy(self, page_slugs): + return ( + self.with_tree_fields() + .extra(where=['tree_path_slugs = %s::varchar(50)[]'], params=[page_slugs]) + .get() + ) + TreeManager = models.Manager.from_queryset(TreeQuerySet) diff --git a/tests/test_import_export.py b/tests/test_import_export.py index ea825a82..160c1bcc 100644 --- a/tests/test_import_export.py +++ b/tests/test_import_export.py @@ -561,3 +561,17 @@ def test_import_export_duplicated_slugs(): import_site(data=json.loads(output)) assert Page.objects.count() == 3 assert Page.objects.filter(parent__isnull=True).count() == 2 + + +def test_import_export_duplicated_subpages_slugs(): + one = Page.objects.create(title='One', slug='one') + dup_one = Page.objects.create(title='Dup', slug='dup', parent=one) + sub_dup_one = Page.objects.create(title='Sub dup one', slug='sub_dup_one', parent=dup_one) + two = Page.objects.create(title='Two', slug='two') + dup_two = Page.objects.create(title='Dup', slug='dup', parent=two) + sub_dup_two = Page.objects.create(title='Sub dup two', slug='sub_dup_two', parent=dup_two) + + output = get_output_of_command('export_site') + Page.objects.all().delete() + import_site(data=json.loads(output)) + assert Page.objects.count() == 6 diff --git a/tests/test_manager.py b/tests/test_manager.py index 93b413f4..63e8a15e 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -937,7 +937,7 @@ def test_site_export_import_json(app, admin_user): resp.form['site_file'] = Upload('site-export.json', site_export, 'application/json') with CaptureQueriesContext(connection) as ctx: resp = resp.form.submit() - assert len(ctx.captured_queries) == 273 + assert len(ctx.captured_queries) == 278 assert set(Page.objects.get(slug='one').related_cells['cell_types']) == {'data_textcell', 'data_linkcell'} assert Page.objects.count() == 4 assert LinkCell.objects.count() == 2 -- 2.30.2