' % (
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index 00d61296f64..01aba7e14b9 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -409,7 +409,7 @@ class View(models.Model):
def _render_template(self, template, values=None):
""" Render the template. If website is enabled on request, then extend rendering context with website values. """
- view = self._get_view(template).sudo()
+ view = self._get(template).sudo()
view._handle_visibility(do_raise=True)
if values is None:
values = {}
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 28b41bad262..db6c8c632d0 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -1090,7 +1090,7 @@ class Website(models.Model):
def get_template(self, template):
if isinstance(template, str) and '.' not in template:
template = 'website.%s' % template
- view = self.env['ir.ui.view']._get_view(template).sudo()
+ view = self.env['ir.ui.view']._get(template).sudo()
if not view:
raise NotFound
return view
diff --git a/odoo/addons/base/models/ir_actions.py b/odoo/addons/base/models/ir_actions.py
index 2828595d525..15e1d4a67ed 100644
--- a/odoo/addons/base/models/ir_actions.py
+++ b/odoo/addons/base/models/ir_actions.py
@@ -218,7 +218,7 @@ class IrActionsActWindow(models.Model):
@api.depends('res_model', 'search_view_id')
def _compute_search_view(self):
for act in self:
- fvg = self.env[act.res_model].fields_view_get(act.search_view_id.id, 'search')
+ fvg = self.env[act.res_model].get_view(act.search_view_id.id, 'search')
act.search_view = str(fvg)
name = fields.Char(string='Action Name', translate=True)
diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py
index 58af110837e..0e4a5e1cf75 100644
--- a/odoo/addons/base/models/ir_module.py
+++ b/odoo/addons/base/models/ir_module.py
@@ -157,8 +157,8 @@ class Module(models.Model):
_order = 'application desc,sequence,name'
@api.model
- def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
- res = super(Module, self).fields_view_get(view_id, view_type, toolbar=toolbar, submenu=False)
+ def get_view(self, view_id=None, view_type='form', **options):
+ res = super().get_view(view_id, view_type, **options)
if view_type == 'form' and res.get('toolbar',False):
install_id = self.env.ref('base.action_server_module_immediate_install').id
action = [rec for rec in res['toolbar']['action'] if rec.get('id', False) != install_id]
diff --git a/odoo/addons/base/models/ir_qweb.py b/odoo/addons/base/models/ir_qweb.py
index 76089bc01fb..bcb50b1888d 100644
--- a/odoo/addons/base/models/ir_qweb.py
+++ b/odoo/addons/base/models/ir_qweb.py
@@ -772,7 +772,7 @@ class IrQWeb(models.AbstractModel):
:rtype: Tuple[Union[etree, str], Optional[str, int]]
"""
IrUIView = self.env['ir.ui.view'].sudo()
- view = IrUIView._get_view(ref)
+ view = IrUIView._get(ref)
template = IrUIView._read_template(view.id)
etree_view = etree.fromstring(template)
diff --git a/odoo/addons/base/models/ir_ui_view.py b/odoo/addons/base/models/ir_ui_view.py
index 75a24ef78a6..385fbeb6f23 100644
--- a/odoo/addons/base/models/ir_ui_view.py
+++ b/odoo/addons/base/models/ir_ui_view.py
@@ -34,6 +34,23 @@ _logger = logging.getLogger(__name__)
MOVABLE_BRANDING = ['data-oe-model', 'data-oe-id', 'data-oe-field', 'data-oe-xpath', 'data-oe-source-id']
+ref_re = re.compile(r"""
+# first match 'form_view_ref' key, backrefs are used to handle single or
+# double quoting of the value
+(['"])(?P
\w+_view_ref)\1
+# colon separator (with optional spaces around)
+\s*:\s*
+# open quote for value
+(['"])
+(?P
+ # we'll just match stuff which is normally part of an xid:
+ # word and "." characters
+ [.\w]+
+)
+# close with same quote as opening
+\3
+""", re.VERBOSE)
+
def quick_eval(expr, globals_dict):
""" Functionally identical to safe_eval(), but optimized with special-casing. """
@@ -967,12 +984,26 @@ actual arch.
del node.attrib['attrs'] # avoid making field visible later
del node.attrib['groups']
+ def _get_view_refs(self, node):
+ """ Extract the `[view_type]_view_ref` keys and values from the node context attribute,
+ giving the views to use for a field node.
+
+ :param node: the field node as an etree
+ :return: a dictonary mapping the `[view_type]_view_ref` key to the xmlid of the view to use for that view type.
+ """
+ if not node.get('context'):
+ return {}
+ return {
+ m.group('view_type'): m.group('view_id')
+ for m in ref_re.finditer(node.get('context'))
+ }
+
#------------------------------------------------------
# Postprocessing: translation, groups and modifiers
#------------------------------------------------------
# TODO: remove group processing from ir_qweb
#------------------------------------------------------
- def postprocess_and_fields(self, node, model=None):
+ def postprocess_and_fields(self, node, model=None, **options):
""" Return an architecture and a description of all the fields.
The field description combines the result of fields_get() and
@@ -987,12 +1018,18 @@ actual arch.
"""
self and self.ensure_one() # self is at most one view
- name_manager = self._postprocess_view(node, model or self.model)
+ name_manager = self._postprocess_view(node, model or self.model, **options)
arch = etree.tostring(node, encoding="unicode").replace('\t', '')
- return arch, dict(name_manager.available_fields)
- def _postprocess_view(self, node, model_name, editable=True):
+ models = set()
+ name_managers = [name_manager]
+ for name_manager in name_managers:
+ models.add(name_manager.model._name)
+ name_managers.extend(name_manager.children)
+ return arch, models
+
+ def _postprocess_view(self, node, model_name, editable=True, parent_name_manager=None, **options):
""" Process the given architecture, modifying it in-place to add and
remove stuff.
@@ -1010,7 +1047,12 @@ actual arch.
self._postprocess_on_change(root, model)
- name_manager = NameManager(model)
+ name_manager = NameManager(model, parent=parent_name_manager)
+
+ root_info = {
+ 'view_type': root.tag,
+ 'mobile': options.get('mobile'),
+ }
# use a stack to recursively traverse the tree
stack = [(root, editable)]
@@ -1020,10 +1062,7 @@ actual arch.
# compute default
tag = node.tag
parent = node.getparent()
- node_info = {
- 'modifiers': {},
- 'editable': editable and self._editable_node(node, name_manager),
- }
+ node_info = dict(root_info, modifiers={}, editable=editable and self._editable_node(node, name_manager))
# tag-specific postprocessing
postprocessor = getattr(self, f"_postprocess_tag_{tag}", None)
@@ -1120,21 +1159,41 @@ actual arch.
node.getparent().remove(node)
# no point processing view-level ``groups`` anymore, return
return
- views = {}
+ if (
+ node_info.get('view_type') == 'form'
+ and field.type in ('one2many', 'many2many')
+ and not node.get('widget')
+ and not node.get('invisible')
+ and not name_manager.parent
+ ):
+ # Embed kanban/tree/form views for visible x2many fields in form views
+ # 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 'form' not in current_view_types:
+ missing_view_types.append('form')
+ 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)
+ if refs:
+ comodel = comodel.with_context(**refs)
+ for view_type in missing_view_types:
+ subarch, _subview = comodel._get_view(view_type=view_type)
+ node.append(subarch)
for child in node:
if child.tag in ('form', 'tree', 'graph', 'kanban', 'calendar'):
- node.remove(child)
- sub_name_manager = self.with_context(
+ node_info['children'] = []
+ self.with_context(
base_model_name=name_manager.model._name,
)._postprocess_view(
- child, field.comodel_name, editable=node_info['editable'],
+ child, field.comodel_name, editable=node_info['editable'], parent_name_manager=name_manager,
)
- xarch = etree.tostring(child, encoding="unicode").replace('\t', '')
- views[child.tag] = {
- 'arch': xarch,
- 'fields': dict(sub_name_manager.available_fields),
- }
- attrs['views'] = views
if field.type in ('many2one', 'many2many'):
comodel = self.env[field.comodel_name].sudo(False)
can_create = comodel.check_access_rights('create', raise_exception=False)
@@ -1160,19 +1219,11 @@ actual arch.
field = name_manager.model._fields.get(name)
if not field or not field.comodel_name:
return
- # move all children nodes into a new node
- groupby_node = E.groupby(*node)
# post-process the node as a nested view, and associate it to the field
- sub_name_manager = self.with_context(
+ self.with_context(
base_model_name=name_manager.model._name,
- )._postprocess_view(groupby_node, field.comodel_name, editable=False)
- xarch = etree.tostring(groupby_node, encoding="unicode").replace('\t', '')
- name_manager.has_field(name, {'views': {
- 'groupby': {
- 'arch': xarch,
- 'fields': dict(sub_name_manager.available_fields),
- }
- }})
+ )._postprocess_view(node, field.comodel_name, editable=False, parent_name_manager=name_manager)
+ name_manager.has_field(name)
def _postprocess_tag_label(self, node, name_manager, node_info):
if node.get('for'):
@@ -1186,7 +1237,7 @@ actual arch.
self.with_context(
base_model_name=name_manager.model._name,
)._postprocess_view(
- searchpanel[0], name_manager.model._name, editable=False,
+ searchpanel[0], name_manager.model._name, editable=False, parent_name_manager=name_manager
)
node_info['children'] = [child for child in node if child.tag != 'searchpanel']
@@ -1839,7 +1890,7 @@ actual arch.
return res_id
@api.model
- def _get_view(self, view_ref):
+ def _get(self, view_ref):
""" Return the view corresponding to ``view_ref``, which may be a
view ID or an XML ID.
"""
@@ -1933,7 +1984,7 @@ actual arch.
@api.model
def render_public_asset(self, template, values=None):
- template_sudo = self._get_view(template).sudo()
+ template_sudo = self._get(template).sudo()
template_sudo._check_view_access()
return self.env['ir.qweb'].sudo()._render(template, values)
@@ -2129,7 +2180,7 @@ class ResetViewArchWizard(models.TransientModel):
class NameManager:
""" An object that manages all the named elements in a view. """
- def __init__(self, model):
+ def __init__(self, model, parent=None):
self.model = model
self.available_fields = collections.defaultdict(dict) # {field_name: field_info}
self.available_actions = set()
@@ -2137,6 +2188,10 @@ class NameManager:
self.mandatory_fields = dict() # {field_name: use}
self.mandatory_parent_fields = dict() # {field_name: use}
self.mandatory_names = dict() # {name: use}
+ self.parent = parent
+ self.children = []
+ if self.parent:
+ self.parent.children.append(self)
@lazy_property
def field_info(self):
diff --git a/odoo/addons/base/models/res_config.py b/odoo/addons/base/models/res_config.py
index f6c05de588d..6e848ce8b4e 100644
--- a/odoo/addons/base/models/res_config.py
+++ b/odoo/addons/base/models/res_config.py
@@ -384,29 +384,22 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
raise UserError(_("Cannot duplicate configuration!"))
@api.model
- def fields_view_get(self, view_id=None, view_type='form',
- toolbar=False, submenu=False):
- ret_val = super(ResConfigSettings, self).fields_view_get(
- view_id=view_id, view_type=view_type,
- toolbar=toolbar, submenu=submenu)
+ def _get_view(self, view_id=None, view_type='form', **options):
+ arch, view = super()._get_view(view_id, view_type, **options)
can_install_modules = self.env['ir.module.module'].check_access_rights(
'write', raise_exception=False)
- doc = etree.XML(ret_val['arch'])
-
- for field in ret_val['fields']:
- if not field.startswith("module_"):
+ for node in arch.xpath("//field[@name]"):
+ if not node.get('name').startswith("module_"):
continue
- for node in doc.xpath("//field[@name='%s']" % field):
- if not can_install_modules:
- node.set("readonly", "1")
- modifiers = json.loads(node.get("modifiers"))
- modifiers['readonly'] = True
- node.set("modifiers", json.dumps(modifiers))
+ if not can_install_modules:
+ node.set("readonly", "1")
+ modifiers = json.loads(node.get("modifiers"))
+ modifiers['readonly'] = True
+ node.set("modifiers", json.dumps(modifiers))
- ret_val['arch'] = etree.tostring(doc, encoding='unicode')
- return ret_val
+ return arch, view
def onchange_module(self, field_value, module_name):
module_sudo = self.env['ir.module.module']._get(module_name[7:])
diff --git a/odoo/addons/base/models/res_currency.py b/odoo/addons/base/models/res_currency.py
index 3b4e8766b5b..bd39b6f51b5 100644
--- a/odoo/addons/base/models/res_currency.py
+++ b/odoo/addons/base/models/res_currency.py
@@ -285,18 +285,16 @@ class Currency(models.Model):
"""
@api.model
- def _fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
- result = super(Currency, self)._fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
+ def _get_view(self, view_id=None, view_type='form', **options):
+ arch, view = super()._get_view(view_id, view_type, **options)
if view_type in ('tree', 'form'):
currency_name = (self.env['res.company'].browse(self._context.get('company_id')) or self.env.company).currency_id.name
- doc = etree.XML(result['arch'])
for field in [['company_rate', _('Unit per %s', currency_name)],
['inverse_company_rate', _('%s per Unit', currency_name)]]:
- node = doc.xpath("//tree//field[@name='%s']" % field[0])
+ node = arch.xpath("//tree//field[@name='%s']" % field[0])
if node:
node[0].set('string', field[1])
- result['arch'] = etree.tostring(doc, encoding='unicode')
- return result
+ return arch, view
class CurrencyRate(models.Model):
@@ -417,18 +415,16 @@ class CurrencyRate(models.Model):
return super()._name_search(parse_date(self.env, name), args, operator, limit, name_get_uid)
@api.model
- def _fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
- result = super(CurrencyRate, self)._fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
+ def _get_view(self, view_id=None, view_type='form', **options):
+ arch, view = super()._get_view(view_id, view_type, **options)
if view_type in ('tree'):
names = {
'company_currency_name': (self.env['res.company'].browse(self._context.get('company_id')) or self.env.company).currency_id.name,
'rate_currency_name': self.env['res.currency'].browse(self._context.get('active_id')).name or 'Unit',
}
- doc = etree.XML(result['arch'])
for field in [['company_rate', _('%(rate_currency_name)s per %(company_currency_name)s', **names)],
['inverse_company_rate', _('%(company_currency_name)s per %(rate_currency_name)s', **names)]]:
- node = doc.xpath("//tree//field[@name='%s']" % field[0])
+ node = arch.xpath("//tree//field[@name='%s']" % field[0])
if node:
node[0].set('string', field[1])
- result['arch'] = etree.tostring(doc, encoding='unicode')
- return result
+ return arch, view
diff --git a/odoo/addons/base/models/res_partner.py b/odoo/addons/base/models/res_partner.py
index bb8df0697fb..54bb10d51ac 100644
--- a/odoo/addons/base/models/res_partner.py
+++ b/odoo/addons/base/models/res_partner.py
@@ -44,26 +44,22 @@ class FormatAddressMixin(models.AbstractModel):
_name = "format.address.mixin"
_description = 'Address Format'
- def _fields_view_get_address(self, arch):
+ def _view_get_address(self, arch):
# consider the country of the user, not the country of the partner we want to display
address_view_id = self.env.company.country_id.address_view_id.sudo()
if address_view_id and not self._context.get('no_address_format') and (not address_view_id.model or address_view_id.model == self._name):
#render the partner address accordingly to address_view_id
- doc = etree.fromstring(arch)
- for address_node in doc.xpath("//div[hasclass('o_address_format')]"):
+ for address_node in arch.xpath("//div[hasclass('o_address_format')]"):
Partner = self.env['res.partner'].with_context(no_address_format=True)
- sub_view = Partner.fields_view_get(
- view_id=address_view_id.id, view_type='form', toolbar=False, submenu=False)
- sub_view_node = etree.fromstring(sub_view['arch'])
+ sub_arch, _sub_view = Partner._get_view(address_view_id.id, 'form')
#if the model is different than res.partner, there are chances that the view won't work
#(e.g fields not present on the model). In that case we just return arch
if self._name != 'res.partner':
try:
- self.env['ir.ui.view'].postprocess_and_fields(sub_view_node, model=self._name)
+ self.env['ir.ui.view'].postprocess_and_fields(sub_arch, model=self._name)
except ValueError:
return arch
- address_node.getparent().replace(address_node, sub_view_node)
- arch = etree.tostring(doc, encoding='unicode')
+ address_node.getparent().replace(address_node, sub_arch)
return arch
class PartnerCategory(models.Model):
@@ -345,13 +341,13 @@ class Partner(models.Model):
partner.commercial_company_name = p.is_company and p.name or partner.company_name
@api.model
- def _fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
+ def _get_view(self, view_id=None, view_type='form', **options):
if (not view_id) and (view_type == 'form') and self._context.get('force_email'):
view_id = self.env.ref('base.view_partner_simple_form').id
- res = super(Partner, self)._fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
+ arch, view = super()._get_view(view_id, view_type, **options)
if view_type == 'form':
- res['arch'] = self._fields_view_get_address(res['arch'])
- return res
+ arch = self._view_get_address(arch)
+ return arch, view
@api.constrains('parent_id')
def _check_parent_id(self):
diff --git a/odoo/addons/base/static/tests/base_settings_tests.js b/odoo/addons/base/static/tests/base_settings_tests.js
index b278b54b59b..1ee83575a37 100644
--- a/odoo/addons/base/static/tests/base_settings_tests.js
+++ b/odoo/addons/base/static/tests/base_settings_tests.js
@@ -206,11 +206,11 @@ QUnit.module('base_settings_tests', {
await legacyExtraNextTick();
assert.hasClass($(target).find(".o_form_view"), "o_form_editable");
assert.verifySteps([
- "load_views", // initial setting action
+ "get_views", // initial setting action
"onchange", // this is a setting view => create new record
"create", // when we click on action button => save
"read", // with save, we have a reload... (not necessary actually)
- "load_views", // for other action in breadcrumb,
+ "get_views", // for other action in breadcrumb,
// with a searchread (not shown here since it is a route)
"onchange", // when we come back, we want to restart from scratch
]);
diff --git a/odoo/addons/base/tests/test_acl.py b/odoo/addons/base/tests/test_acl.py
index 0f7f38f1c5e..9d2b8c120eb 100644
--- a/odoo/addons/base/tests/test_acl.py
+++ b/odoo/addons/base/tests/test_acl.py
@@ -48,7 +48,7 @@ class TestACL(TransactionCaseWithUserDemo):
# Verify the test environment first
original_fields = currency.fields_get([])
- form_view = currency.fields_view_get(False, 'form')
+ form_view = currency.get_view(False, 'form')
view_arch = etree.fromstring(form_view.get('arch'))
has_group_system = self.user_demo.has_group(GROUP_SYSTEM)
self.assertFalse(has_group_system, "`demo` user should not belong to the restricted group before the test")
@@ -62,7 +62,7 @@ class TestACL(TransactionCaseWithUserDemo):
self._set_field_groups(currency, 'decimal_places', GROUP_SYSTEM)
fields = currency.fields_get([])
- form_view = currency.fields_view_get(False, 'form')
+ form_view = currency.get_view(False, 'form')
view_arch = etree.fromstring(form_view.get('arch'))
self.assertNotIn('decimal_places', fields, "'decimal_places' field should be gone")
self.assertEqual(view_arch.xpath("//field[@name='decimal_places']"), [],
@@ -74,7 +74,7 @@ class TestACL(TransactionCaseWithUserDemo):
self.erp_system_group.users += self.user_demo
has_group_system = self.user_demo.has_group(GROUP_SYSTEM)
fields = currency.fields_get([])
- form_view = currency.fields_view_get(False, 'form')
+ form_view = currency.get_view(False, 'form')
view_arch = etree.fromstring(form_view.get('arch'))
self.assertTrue(has_group_system, "`demo` user should now belong to the restricted group")
self.assertIn('decimal_places', fields, "'decimal_places' field must be properly visible again")
@@ -130,7 +130,7 @@ class TestACL(TransactionCaseWithUserDemo):
""" Test form view Create, Edit, Delete button visibility based on access right of model"""
methods = ['create', 'edit', 'delete']
company = self.env['res.company'].with_user(self.user_demo)
- company_view = company.fields_view_get(False, 'form')
+ company_view = company.get_view(False, 'form')
view_arch = etree.fromstring(company_view['arch'])
for method in methods:
self.assertEqual(view_arch.get(method), 'false')
@@ -140,7 +140,7 @@ class TestACL(TransactionCaseWithUserDemo):
self.erp_system_group.users += self.user_demo
methods = ['create', 'edit', 'delete']
company = self.env['res.company'].with_user(self.user_demo)
- company_view = company.fields_view_get(False, 'form')
+ company_view = company.get_view(False, 'form')
view_arch = etree.fromstring(company_view['arch'])
for method in methods:
self.assertIsNone(view_arch.get(method))
@@ -149,7 +149,7 @@ class TestACL(TransactionCaseWithUserDemo):
""" Test many2one field Create and Edit option visibility based on access rights of relation field"""
methods = ['create', 'write']
company = self.env['res.company'].with_user(self.user_demo)
- company_view = company.fields_view_get(False, 'form')
+ company_view = company.get_view(False, 'form')
view_arch = etree.fromstring(company_view['arch'])
field_node = view_arch.xpath("//field[@name='currency_id']")
self.assertTrue(len(field_node), "currency_id field should be in company from view")
@@ -161,7 +161,7 @@ class TestACL(TransactionCaseWithUserDemo):
self.erp_system_group.users += self.user_demo
methods = ['create', 'write']
company = self.env['res.company'].with_user(self.user_demo)
- company_view = company.fields_view_get(False, 'form')
+ company_view = company.get_view(False, 'form')
view_arch = etree.fromstring(company_view['arch'])
field_node = view_arch.xpath("//field[@name='currency_id']")
self.assertTrue(len(field_node), "currency_id field should be in company from view")
diff --git a/odoo/addons/base/tests/test_translate.py b/odoo/addons/base/tests/test_translate.py
index a8586eeaaa1..2f50c1faac6 100644
--- a/odoo/addons/base/tests/test_translate.py
+++ b/odoo/addons/base/tests/test_translate.py
@@ -638,8 +638,8 @@ class TestTranslationWrite(TransactionCase):
self.assertEqual(fg['state']['selection'],
[('manual', 'Custo'), ('base', 'Pas touche!')])
- def test_fields_view_get(self):
- """ Test translations of field descriptions in fields_view_get(). """
+ def test_load_views(self):
+ """ Test translations of field descriptions in get_view(). """
self.env['res.lang']._activate_lang('fr_FR')
# add translation for the string of field ir.model.name
@@ -659,9 +659,9 @@ class TestTranslationWrite(TransactionCase):
info = model.fields_get(['name'])
self.assertEqual(info['name']['string'], LABEL)
- # check that fields_view_get() also returns the expected label
- info = model.fields_view_get()['fields']
- self.assertEqual(info['name']['string'], LABEL)
+ # check that get_views() also returns the expected label
+ info = model.get_views([(False, 'form')])
+ self.assertEqual(info['models'][model._name]['name']['string'], LABEL)
class TestXMLTranslation(TransactionCase):
diff --git a/odoo/addons/base/tests/test_views.py b/odoo/addons/base/tests/test_views.py
index b0d6f2ce91a..74bd758eafa 100644
--- a/odoo/addons/base/tests/test_views.py
+++ b/odoo/addons/base/tests/test_views.py
@@ -1256,9 +1256,7 @@ class TestViews(ViewCase):
"""
})
- view = self.View.with_context(check_view_ids=[view2.id, view3.id]) \
- .fields_view_get(view2.id, view_type='form')
- self.assertEqual(view['type'], 'form')
+ view = self.View.with_context(check_view_ids=[view2.id, view3.id]).get_view(view2.id, 'form')
self.assertEqual(
etree.fromstring(
view['arch'],
@@ -1285,8 +1283,7 @@ class TestViews(ViewCase):
'inherit_id': view1.id,
'arch': '',
})
- view = self.View.with_context(check_view_ids=view2.ids).fields_view_get(view1.id)
- self.assertEqual(view['type'], 'form')
+ view = self.View.with_context(check_view_ids=view2.ids).get_view(view1.id)
self.assertEqual(
view['arch'],
'',
@@ -1305,8 +1302,7 @@ class TestViews(ViewCase):
'inherit_id': view1.id,
'arch': '',
})
- view = self.View.with_context(check_view_ids=view2.ids).fields_view_get(view1.id)
- self.assertEqual(view['type'], 'form')
+ view = self.View.with_context(check_view_ids=view2.ids).get_view(view1.id)
self.assertEqual(
view['arch'],
'',
@@ -1325,8 +1321,7 @@ class TestViews(ViewCase):
'inherit_id': view1.id,
'arch': '',
})
- view = self.View.with_context(check_view_ids=view2.ids).fields_view_get(view1.id)
- self.assertEqual(view['type'], 'form')
+ view = self.View.with_context(check_view_ids=view2.ids).get_view(view1.id)
self.assertEqual(
view['arch'],
'',
@@ -1379,8 +1374,7 @@ class TestViews(ViewCase):
})
view = self.View.with_context(check_view_ids=[view2.id, view3.id]) \
- .fields_view_get(view2.id, view_type='form')
- self.assertEqual(view['type'], 'form')
+ .get_view(view2.id, view_type='form')
self.assertEqual(
etree.fromstring(
view['arch'],
@@ -2330,13 +2324,13 @@ class TestViews(ViewCase):
})
# default view, no address_view defined
- arch = self.env['res.partner'].fields_view_get(view_id=partner_view.id)['arch']
+ arch = self.env['res.partner'].get_view(partner_view.id)['arch']
self.assertIn('"street"', arch)
self.assertNotIn('"parent_name"', arch)
# custom view, address_view defined
self.env.company.country_id.address_view_id = address_view
- arch = self.env['res.partner'].fields_view_get(view_id=partner_view.id)['arch']
+ arch = self.env['res.partner'].get_view(partner_view.id)['arch']
self.assertNotIn('"street"', arch)
self.assertIn('"parent_name"', arch)
# weird result: