From 681e0ea0440db1ac7d9990f5ebd7f10c0c17c77c Mon Sep 17 00:00:00 2001 From: Lucas Perais Date: Tue, 22 Nov 2022 15:03:55 +0000 Subject: [PATCH] [FIX] base: ir_ui_view: factorize inlining of default subview of x2many The new get_views API inlines every subview into the main view in an effort to optimize client/server communication. In the situation: ```
``` The server algorithm will fetch kanban or list views to display that x2many and inline them in the final arch that is sent to the client. This commit aims at factorizing the code which does just that in order for studio (or other modules) to be able to detect whether the subview it receives is "real" or inlined closes odoo/odoo#106504 X-original-commit: fcf71e51e80b54d709ffbfc5639cc913746ac684 Related: odoo/enterprise#34376 Signed-off-by: Denis Ledoux (dle) Signed-off-by: Lucas Perais (lpe) --- odoo/addons/base/models/ir_ui_view.py | 45 +++++++++++++++++---------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/odoo/addons/base/models/ir_ui_view.py b/odoo/addons/base/models/ir_ui_view.py index e8d730453a1..5c26c00d457 100644 --- a/odoo/addons/base/models/ir_ui_view.py +++ b/odoo/addons/base/models/ir_ui_view.py @@ -1216,6 +1216,31 @@ actual arch. if not node.get('on_change'): node.set('on_change', '1') + def _get_x2many_missing_view_archs(self, field, field_node, node_info): + """ + For x2many fields that require to have some multi-record arch (kanban or list) to display the records + be available, this function fetches all arch that are needed and return them. + The caller function is responsible to do what it needs with them. + """ + current_view_types = [el.tag for el in field_node.xpath("./*[descendant::field]")] + missing_view_types = [] + if not any(view_type in current_view_types for view_type in field_node.get('mode', 'kanban,tree').split(',')): + missing_view_types.append( + field_node.get('mode', 'kanban' if node_info.get('mobile') else 'tree').split(',')[0] + ) + + if not missing_view_types: + return [] + + comodel = self.env[field.comodel_name].sudo(False) + refs = self._get_view_refs(field_node) + # Do not propagate _view_ref of parent call to `_get_view` + comodel = comodel.with_context(**{ + f'{view_type}_view_ref': refs.get(f'{view_type}_view_ref') + for view_type in missing_view_types + }) + + return [comodel._get_view(view_type=view_type) for view_type in missing_view_types] #------------------------------------------------------ # Specific node postprocessors @@ -1260,23 +1285,9 @@ actual arch. # if no widget or the widget requires it. # So the web client doesn't have to call `get_views` for x2many fields not embedding their view # in the main form view. - current_view_types = [el.tag for el in node.xpath("./*[descendant::field]")] - missing_view_types = [] - if not any(view_type in current_view_types for view_type in node.get('mode', 'kanban,tree').split(',')): - missing_view_types.append( - node.get('mode', 'kanban' if node_info.get('mobile') else 'tree').split(',')[0] - ) - if missing_view_types: - comodel = self.env[field.comodel_name].sudo(False) - refs = self._get_view_refs(node) - # Do not propagate _view_ref of parent call to `_get_view` - comodel = comodel.with_context(**{ - f'{view_type}_view_ref': refs.get(f'{view_type}_view_ref') - for view_type in missing_view_types - }) - for view_type in missing_view_types: - subarch, _subview = comodel._get_view(view_type=view_type) - node.append(subarch) + for arch, _view in self._get_x2many_missing_view_archs(field, node, node_info): + node.append(arch) + for child in node: if child.tag in ('form', 'tree', 'graph', 'kanban', 'calendar'): node_info['children'] = []