From 7718199ae08caeb97f1ae35acef8312015c6e7f9 Mon Sep 17 00:00:00 2001 From: Jorge Pinna Puissant Date: Mon, 24 Feb 2020 14:43:54 +0000 Subject: [PATCH] [FIX] base, website: process views without xml_id The function get_inheriting_views_arch, retrieves the architecture of views that inherit from the given view. In the case of the module init is currently in process only views from modules whose code is already loaded are taken into account. Before this commit, the function didn't process views that has been copied (copy on write, web editor, customize show, manual copy, ...), this raise an error when trying to install a module. For example, install module website_sale, copy on write the view 'Main layout', install module website_sale_wishlist. Now, views that has been copied are also processed. opw-2181968 closes odoo/odoo#47590 X-original-commit: d5a2890b30f869c9b4cf7aafed0e05aff9440360 Signed-off-by: Jorge Pinna Puissant (jpp) Co-authored-by: Nicolas Lempereur --- addons/website/models/ir_ui_view.py | 25 ++++++++++++++ addons/website/tests/test_views.py | 48 +++++++++++++++++++++++++++ odoo/addons/base/models/ir_ui_view.py | 15 ++++++--- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py index 46a89a76d41..c2eb62acfb5 100644 --- a/addons/website/models/ir_ui_view.py +++ b/addons/website/models/ir_ui_view.py @@ -272,6 +272,31 @@ class View(models.Model): # prefer inactive website-specific views over active generic ones return views.filter_duplicate().filtered('active') + @api.model + def _get_filter_xmlid_query(self): + """This method add some specific view that do not have XML ID + """ + if not self._context.get('website_id'): + return super()._get_filter_xmlid_query() + else: + return """SELECT res_id + FROM ir_model_data + WHERE res_id IN %(res_ids)s + AND model = 'ir.ui.view' + AND module IN %(modules)s + UNION + SELECT sview.id + FROM ir_ui_view sview + INNER JOIN ir_ui_view oview USING (key) + INNER JOIN ir_model_data d + ON oview.id = d.res_id + AND d.model = 'ir.ui.view' + AND d.module IN %(modules)s + WHERE sview.id IN %(res_ids)s + AND sview.website_id IS NOT NULL + AND oview.website_id IS NULL; + """ + @api.model @tools.ormcache_context('self.env.uid', 'self.env.su', 'xml_id', keys=('website_id',)) def get_view_id(self, xml_id): diff --git a/addons/website/tests/test_views.py b/addons/website/tests/test_views.py index 3b43f058d68..ad060103d24 100644 --- a/addons/website/tests/test_views.py +++ b/addons/website/tests/test_views.py @@ -896,6 +896,54 @@ class TestCowViewSaving(common.TransactionCase): # 5 | Extension | , extended content | 1 | 4 | website.extension_view # 3 | Extension 2 | , extended content 2 | 1 | 5 | website.extension_view_2 + def test_cow_extension_with_install(self): + View = self.env['ir.ui.view'] + # Base + v1 = View.create({ + 'name': 'Base', + 'type': 'qweb', + 'arch': '
base content
', + 'key': 'website.base_view_v1', + }).with_context(load_all_views=True) + self.env['ir.model.data'].create({ + 'module': 'website', + 'name': 'base_view_v1', + 'model': v1._name, + 'res_id': v1.id, + }) + + # Extension + v2 = View.create({ + 'name': 'Extension', + 'mode': 'extension', + 'inherit_id': v1.id, + 'arch': '
extended content
', + 'key': 'website.extension_view_v2', + }) + self.env['ir.model.data'].create({ + 'module': 'website', + 'name': 'extension_view_v2', + 'model': v2._name, + 'res_id': v2.id, + }) + + # multiwebsite specific + v1.with_context(website_id=1).write({'name': 'Extension Specific'}) + + original_pool_init = View.pool._init + View.pool._init = True + + try: + # Simulate module install + View._load_records([dict(xml_id='website.extension2_view', values={ + 'name': ' ---', + 'mode': 'extension', + 'inherit_id': v1.id, + 'arch': '

EXTENSION

', + 'key': 'website.extension2_view', + })]) + finally: + View.pool._init = original_pool_init @tagged('-at_install', 'post_install') class Crawler(HttpCase): diff --git a/odoo/addons/base/models/ir_ui_view.py b/odoo/addons/base/models/ir_ui_view.py index 10fdd4d0eb7..efa4dcce214 100644 --- a/odoo/addons/base/models/ir_ui_view.py +++ b/odoo/addons/base/models/ir_ui_view.py @@ -526,6 +526,14 @@ actual arch. ['active', '=', True], ] + @api.model + def _get_filter_xmlid_query(self): + """This method is meant to be overridden by other modules. + """ + return """SELECT res_id FROM ir_model_data + WHERE res_id IN %(res_ids)s AND model = 'ir.ui.view' AND module IN %(modules)s + """ + def get_inheriting_views_arch(self, model): """Retrieves the sets of views that should currently be used in the system in the right order. During the module upgrade phase it @@ -571,11 +579,8 @@ actual arch. ids_to_check = [vid for vid in view_ids if vid not in check_view_ids] if ids_to_check: loaded_modules = tuple(self.pool._init_modules) + (self._context.get('install_module'),) - query = """ - SELECT res_id FROM ir_model_data - WHERE res_id IN %s AND model = 'ir.ui.view' AND module IN %s - """ - self.env.cr.execute(query, [tuple(ids_to_check), loaded_modules]) + query = self._get_filter_xmlid_query() + self.env.cr.execute(query, {'res_ids': tuple(ids_to_check), 'modules': loaded_modules}) valid_view_ids = [r[0] for r in self.env.cr.fetchall()] + check_view_ids view_ids = [vid for vid in view_ids if vid in valid_view_ids]