[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) <rco@openerp.com>
This commit is contained in:
Raphael Collet
2021-04-22 08:59:36 +00:00
parent 93d2321b6b
commit f7d5d11238
5 changed files with 22 additions and 2 deletions
+7 -1
View File
@@ -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
+2
View File
@@ -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]
+2
View File
@@ -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)
+5
View File
@@ -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:
+6 -1
View File
@@ -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