From f7d5d11238043f9d85d49c253d40fa19d006f0fc Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 13 Apr 2021 15:49:19 +0000 Subject: [PATCH] [IMP] core: do not add magic and inherited fields on abstract models Magic and inherited fields are not really useful on abstract models. The _inherits specification is used anyway by models that inherit from those abstract models. The main goal of this change is to prepare a refactoring of models where fields are no longer duplicated on the registry classes, but fields defined on classes are used directly. But this new design cannot be applied to all fields: a field being overridden simply cannot be used directly. This branch improves the situation by avoiding unnecessary field overridings. closes odoo/odoo#69372 Related: odoo/upgrade#2409 Signed-off-by: Raphael Collet (rco) --- addons/board/models/board.py | 8 +++++++- odoo/addons/base/models/ir_model.py | 2 ++ odoo/addons/base/models/res_users.py | 2 ++ odoo/fields.py | 5 +++++ odoo/models.py | 7 ++++++- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/addons/board/models/board.py b/addons/board/models/board.py index 738f9850e08..3d7a47f7574 100644 --- a/addons/board/models/board.py +++ b/addons/board/models/board.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, models +from odoo import api, fields, models class Board(models.AbstractModel): @@ -9,6 +9,12 @@ class Board(models.AbstractModel): _description = "Board" _auto = False + # This is necessary for when the web client opens a dashboard. Technically + # speaking, the dashboard is a form view, and opening it makes the client + # initialize a dummy record by invoking onchange(). And the latter requires + # an 'id' field to work properly... + id = fields.Id() + @api.model_create_multi def create(self, vals_list): return self diff --git a/odoo/addons/base/models/ir_model.py b/odoo/addons/base/models/ir_model.py index 5777683d53f..ae15a0a9e98 100644 --- a/odoo/addons/base/models/ir_model.py +++ b/odoo/addons/base/models/ir_model.py @@ -1023,6 +1023,8 @@ class IrModelFields(models.Model): model_id = self.env['ir.model']._get_id(model_name) for field in self.env[model_name]._fields.values(): rows.append(self._reflect_field_params(field, model_id)) + if not rows: + return cols = list(unique(['model', 'name'] + list(rows[0]))) expected = [tuple(row[col] for col in cols) for row in rows] diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py index d53f7d94d1d..832dafdc6ad 100644 --- a/odoo/addons/base/models/res_users.py +++ b/odoo/addons/base/models/res_users.py @@ -1726,4 +1726,6 @@ class APIKeyDescription(models.TransientModel): class APIKeyShow(models.AbstractModel): _name = _description = 'res.users.apikeys.show' + # the field 'id' is necessary for the onchange that returns the value of 'key' + id = fields.Id() key = fields.Char(readonly=True) diff --git a/odoo/fields.py b/odoo/fields.py index fcca4a323fe..6072bafbe26 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -495,10 +495,15 @@ class Field(MetaField('DummyField', (object,), {})): # special cases of inherited fields if self.inherited: + self.inherited_field = field if not self.states: self.states = field.states if field.required: self.required = True + # add modules from delegate and target fields; the first one ensures + # that inherited fields introduced via an abstract model (_inherits + # being on the abstract model) are assigned an XML id + self._modules.update(model._fields[self.related[0]]._modules) self._modules.update(field._modules) if self._depends_context is not None: diff --git a/odoo/models.py b/odoo/models.py index e4a7df6b1b9..be9955de020 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -438,6 +438,9 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): >>> str(datetime.datetime.utcnow()) '2013-06-18 08:31:32.821177' """ + if self._abstract: + return + def add(name, field): """ add ``field`` with the given ``name`` if it does not exist yet """ if name not in self._fields: @@ -2534,6 +2537,8 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): return True def _check_removed_columns(self, log=False): + if self._abstract: + return # iterate on the database columns to drop the NOT NULL constraints of # fields which were required but have been removed (or will be added by # another module) @@ -2714,7 +2719,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): @api.model def _add_inherited_fields(self): """ Determine inherited fields. """ - if not self._inherits: + if self._abstract or not self._inherits: return # determine which fields can be inherited