From 16f9375dab793b802fb13467d6b70821373d3df2 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Fri, 31 May 2019 08:24:49 +0000 Subject: [PATCH] [FIX] website: website-specific child views On a eCommerce page were there was no SEO optimization change: - Customize > Activate "eCommerce categories" - Customize > Activate "Colapsible category list" - Promote > Optimize SEO > Change description > Save Nothing happens. Actually, an SQL error is raised because of the `ondelete='restrict'` set at: https://github.com/odoo/odoo/blob/897feb553e6ef75af9434cb77436b26abde3a761/odoo/addons/base/models/ir_ui_view.py#L212 In this case, we have the following structure: ``` View 1 | ---> View 2 (Website-specific) | ---> View 3 (Website-specific) ``` For example: ``` Products | ---> eCommerce Categories (Website-specific) | ---> Collapsible Category List (Website-specific) ``` Since the inherited view (View 2) is website-specific, we duplicate it and try to unlink it. However, this view has children, which raises the error. To solve the issue, we re-attach the children of the inherited view to its copy. In a realistic situation, the children of a website-specific view should also be website-specific, so there is no need to apply the 'copy or re-attach' logic recursively. We end up with: ``` View 1 (Website-specific, duplicated) | ---> View 2 (Website-specific, duplicated) | ---> View 3 (Website-specific) ``` opw-1997946 closes odoo/odoo#33787 Signed-off-by: Nicolas Martinelli (nim) --- addons/website/models/ir_ui_view.py | 3 +- addons/website/tests/test_views.py | 48 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py index 66d2d8ea363..93c5fb373b2 100644 --- a/addons/website/models/ir_ui_view.py +++ b/addons/website/models/ir_ui_view.py @@ -83,7 +83,8 @@ class View(models.Model): # original tree. Indeed, the order of children 'id' fields # must remain the same so that the inheritance is applied # in the same order in the copied tree. - inherit_child.copy({'inherit_id': website_specific_view.id, 'key': inherit_child.key}) + child = inherit_child.copy({'inherit_id': website_specific_view.id, 'key': inherit_child.key}) + inherit_child.inherit_children_ids.write({'inherit_id': child.id}) inherit_child.unlink() else: # Trigger COW on inheriting views diff --git a/addons/website/tests/test_views.py b/addons/website/tests/test_views.py index bb847ba9f6a..0d24a2517ad 100644 --- a/addons/website/tests/test_views.py +++ b/addons/website/tests/test_views.py @@ -797,6 +797,54 @@ class TestCowViewSaving(common.TransactionCase): all_title_updated = specific_view.website_meta_title == self.base_view.website_meta_title == "A bug got fixed by updating this field" self.assertEqual(all_title_updated, True, "Update on top level generic views should also be applied on specific views") + def test_multiple_inherit_level(self): + """ Test multi-level inheritance: + Base + | + ---> Extension (Website-specific) + | + ---> Extension 2 (Website-specific) + """ + View = self.env['ir.ui.view'] + + self.inherit_view.website_id = 1 + inherit_view_2 = View.create({ + 'name': 'Extension 2', + 'mode': 'extension', + 'inherit_id': self.inherit_view.id, + 'arch': '
, extended content 2
', + 'key': 'website.extension_view_2', + 'website_id': 1, + }) + + total_views = View.search_count([]) + + # id | name | content | website_id | inherit | key + # -------------------------------------------------------------------------------------------- + # 1 | Base | base content | / | / | website.base_view + # 2 | Extension | , extended content | 1 | 1 | website.extension_view + # 3 | Extension 2 | , extended content 2 | 1 | 2 | website.extension_view_2 + + self.base_view.with_context(website_id=1).write({'arch': '
modified content
'}) + + # 2 views are created, one is deleted + self.assertEqual(View.search_count([]), total_views + 1) + self.assertFalse(self.inherit_view.exists()) + self.assertTrue(inherit_view_2.exists()) + + # Verify the inheritance + base_specific = View.search([('key', '=', self.base_view.key), ('website_id', '=', 1)]).with_context(load_all_views=True) + extend_specific = View.search([('key', '=', 'website.extension_view'), ('website_id', '=', 1)]) + self.assertEqual(extend_specific.inherit_id, base_specific) + self.assertEqual(inherit_view_2.inherit_id, extend_specific) + + # id | name | content | website_id | inherit | key + # -------------------------------------------------------------------------------------------- + # 1 | Base | base content | / | / | website.base_view + # 4 | Base | modified content | 1 | / | website.base_view + # 5 | Extension | , extended content | 1 | 4 | website.extension_view + # 3 | Extension 2 | , extended content 2 | 1 | 5 | website.extension_view_2 + class Crawler(HttpCase): def setUp(self):