pool._store_function[model].sort(key=lambda x: x[4])
@classmethod
- def _init_manual_fields(cls, pool, cr):
+ def _init_manual_fields(cls, cr):
# Check whether the query is already done
- if pool.fields_by_model is not None:
- manual_fields = pool.fields_by_model.get(cls._name, [])
+ if cls.pool.fields_by_model is not None:
+ manual_fields = cls.pool.fields_by_model.get(cls._name, [])
else:
cr.execute('SELECT * FROM ir_model_fields WHERE model=%s AND state=%s', (cls._name, 'manual'))
manual_fields = cr.dictfetchall()
cls._onchange_methods = defaultdict(list)
for attr, func in getmembers(cls, callable):
if hasattr(func, '_constrains'):
- if not all(name in cls._fields for name in func._constrains):
- _logger.warning("@constrains%r parameters must be field names", func._constrains)
cls._constraint_methods.append(func)
if hasattr(func, '_onchange'):
- if not all(name in cls._fields for name in func._onchange):
- _logger.warning("@onchange%r parameters must be field names", func._onchange)
for name in func._onchange:
cls._onchange_methods[name].append(func)
# register stuff about low-level function fields and custom fields
cls._init_function_fields(pool, cr)
- cls._init_manual_fields(pool, cr)
-
- # process _inherits
- cls._inherits_check()
- cls._inherits_reload()
# register constraints and onchange methods
cls._init_constraints_onchanges()
- # check defaults
- for k in cls._defaults:
- assert k in cls._fields, \
- "Model %s has a default for nonexiting field %s" % (cls._name, k)
-
- # restart columns
- for column in cls._columns.itervalues():
- column.restart()
-
- # validate rec_name
- if cls._rec_name:
- assert cls._rec_name in cls._fields, \
- "Invalid rec_name %s for model %s" % (cls._rec_name, cls._name)
- elif 'name' in cls._fields:
- cls._rec_name = 'name'
-
# prepare ormcache, which must be shared by all instances of the model
cls._ormcache = {}
#
@classmethod
- def _inherits_reload_src(cls):
- """ Recompute the _inherit_fields mapping on each _inherits'd child model."""
- for model in cls.pool.values():
- if cls._name in model._inherits:
- model._inherits_reload()
-
- @classmethod
def _inherits_reload(cls):
- """ Recompute the _inherit_fields mapping.
-
- This will also call itself on each inherits'd child model.
+ """ Recompute the _inherit_fields mapping, and inherited fields. """
+ struct = {}
+ fields = {}
+ for parent_model, parent_field in cls._inherits.iteritems():
+ parent = cls.pool[parent_model]
+ # old-api struct for _inherit_fields
+ for name, column in parent._columns.iteritems():
+ struct[name] = (parent_model, parent_field, column, parent_model)
+ for name, source in parent._inherit_fields.iteritems():
+ struct[name] = (parent_model, parent_field, source[2], source[3])
+ # new-api fields for _fields
+ for name, field in parent._fields.iteritems():
+ fields[name] = field.new(
+ inherited=True,
+ related=(parent_field, name),
+ related_sudo=False,
+ )
- """
- res = {}
- for table in cls._inherits:
- other = cls.pool[table]
- for col in other._columns.keys():
- res[col] = (table, cls._inherits[table], other._columns[col], table)
- for col in other._inherit_fields.keys():
- res[col] = (table, cls._inherits[table], other._inherit_fields[col][2], other._inherit_fields[col][3])
- cls._inherit_fields = res
+ # old-api stuff
+ cls._inherit_fields = struct
cls._all_columns = cls._get_column_infos()
- # interface inherited fields with new-style fields (note that the
- # reverse order is for being consistent with _all_columns above)
- for parent_model, parent_field in reversed(cls._inherits.items()):
- for attr, field in cls.pool[parent_model]._fields.iteritems():
- if attr not in cls._fields:
- cls._add_field(attr, field.new(
- inherited=True,
- related=(parent_field, attr),
- related_sudo=False,
- ))
-
- cls._inherits_reload_src()
+ # add inherited fields that are not redefined locally
+ for name, field in fields.iteritems():
+ if name not in cls._fields:
+ cls._add_field(name, field)
@classmethod
def _get_column_infos(cls):
@api.model
def _prepare_setup_fields(self):
""" Prepare the setup of fields once the models have been loaded. """
- for field in self._fields.itervalues():
- field.reset()
+ type(self)._setup_done = False
+ for name, field in self._fields.items():
+ if field.inherited:
+ del self._fields[name]
+ else:
+ field.reset()
@api.model
- def _setup_fields(self, partial=False):
+ def _setup_fields(self):
""" Setup the fields (dependency triggers, etc). """
- for field in self._fields.itervalues():
- try:
- field.setup(self.env)
- except Exception:
- if not partial:
- raise
+ cls = type(self)
+ if cls._setup_done:
+ return
+ cls._setup_done = True
+
+ # first make sure that parent models are all set up
+ for parent in self._inherits:
+ self.env[parent]._setup_fields()
+
+ # retrieve custom fields
+ if not self._context.get('_setup_fields_partial'):
+ cls._init_manual_fields(self._cr)
+
+ # retrieve inherited fields
+ cls._inherits_check()
+ cls._inherits_reload()
+
+ # set up fields
+ for field in cls._fields.itervalues():
+ field.setup(self.env)
- # update columns (fields may have changed), and column_infos
- for name, field in self._fields.iteritems():
+ # update columns (fields may have changed)
+ for name, field in cls._fields.iteritems():
if field.column:
- self._columns[name] = field.to_column()
- self._inherits_reload()
+ cls._columns[name] = field.to_column()
# group fields by compute to determine field.computed_fields
fields_by_compute = defaultdict(list)
- for field in self._fields.itervalues():
+ for field in cls._fields.itervalues():
if field.compute:
field.computed_fields = fields_by_compute[field.compute]
field.computed_fields.append(field)
else:
field.computed_fields = []
+ # check constraints
+ for func in cls._constraint_methods:
+ if not all(name in cls._fields for name in func._constrains):
+ _logger.warning("@constrains%r parameters must be field names", func._constrains)
+ for name in cls._onchange_methods:
+ if name not in cls._fields:
+ func = cls._onchange_methods[name]
+ _logger.warning("@onchange%r parameters must be field names", func._onchange)
+
+ # check defaults
+ for name in cls._defaults:
+ assert name in cls._fields, \
+ "Model %s has a default for nonexiting field %s" % (cls._name, name)
+
+ # validate rec_name
+ if cls._rec_name:
+ assert cls._rec_name in cls._fields, \
+ "Invalid rec_name %s for model %s" % (cls._rec_name, cls._name)
+ elif 'name' in cls._fields:
+ cls._rec_name = 'name'
+
def fields_get(self, cr, user, allfields=None, context=None, write_access=True):
""" fields_get([fields])