diff options
| -rw-r--r-- | odoo/fields.py | 16 | ||||
| -rw-r--r-- | odoo/models.py | 47 | ||||
| -rw-r--r-- | odoo/modules/registry.py | 20 |
3 files changed, 45 insertions, 38 deletions
diff --git a/odoo/fields.py b/odoo/fields.py index ad0c167588f..2f4764f6233 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -594,18 +594,22 @@ class Field(MetaField('DummyField', (object,), {})): # Setup of field triggers # - def resolve_depends(self, model): + def resolve_depends(self, registry): """ Return the dependencies of `self` as a collection of field tuples. """ + Model0 = registry[self.model_name] + for dotnames in self.depends: field_seq = [] - field_model = model + model_name = self.model_name + for index, fname in enumerate(dotnames.split('.')): - if model._transient and not field_model._transient: + Model = registry[model_name] + if Model0._transient and not Model._transient: # modifying fields on regular models should not trigger # recomputations of fields on transient models break - field = field_model._fields[fname] + field = Model._fields[fname] if field is self and index: self.recursive = True @@ -618,10 +622,10 @@ class Field(MetaField('DummyField', (object,), {})): yield tuple(field_seq) if field.type in ('one2many', 'many2many'): - for inv_field in field_model._field_inverses[field]: + for inv_field in Model._field_inverses[field]: yield tuple(field_seq) + (inv_field,) - field_model = model.env.get(field.comodel_name) + model_name = field.comodel_name ############################################################################ # diff --git a/odoo/models.py b/odoo/models.py index 1ccdfd55ec0..9b8bd13d507 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2780,27 +2780,6 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): """ Setup recomputation triggers, and complete the model setup. """ cls = type(self) - # The triggers of a field F is a tree that contains the fields that - # depend on F, together with the fields to inverse to find out which - # records to recompute. - # - # For instance, assume that G depends on F, H depends on X.F, I depends - # on W.X.F, and J depends on Y.F. The triggers of F will be the tree: - # - # [G] - # X/ \Y - # [H] [J] - # W/ - # [I] - # - # This tree provides perfect support for the trigger mechanism: - # when F is # modified on records, - # - mark G to recompute on records, - # - mark H to recompute on inverse(X, records), - # - mark I to recompute on inverse(W, inverse(X, records)), - # - mark J to recompute on inverse(Y, records). - cls._field_triggers = cls.pool.field_triggers - # register constraints and onchange methods cls._init_constraints_onchanges() @@ -5732,13 +5711,33 @@ Record ids: %(records)s """ if not self or not fnames: return + + # The triggers of a field F is a tree that contains the fields that + # depend on F, together with the fields to inverse to find out which + # records to recompute. + # + # For instance, assume that G depends on F, H depends on X.F, I depends + # on W.X.F, and J depends on Y.F. The triggers of F will be the tree: + # + # [G] + # X/ \Y + # [H] [J] + # W/ + # [I] + # + # This tree provides perfect support for the trigger mechanism: + # when F is # modified on records, + # - mark G to recompute on records, + # - mark H to recompute on inverse(X, records), + # - mark I to recompute on inverse(W, inverse(X, records)), + # - mark J to recompute on inverse(Y, records). if len(fnames) == 1: - tree = self._field_triggers.get(self._fields[next(iter(fnames))]) + tree = self.pool.field_triggers.get(self._fields[next(iter(fnames))]) else: # merge dependency trees to evaluate all triggers at once tree = {} for fname in fnames: - node = self._field_triggers.get(self._fields[fname]) + node = self.pool.field_triggers.get(self._fields[fname]) if node: trigger_tree_merge(tree, node) if tree: @@ -5865,7 +5864,7 @@ Record ids: %(records)s yield from val else: yield from traverse(val) - return traverse(self._field_triggers.get(field, {})) + return traverse(self.pool.field_triggers.get(field, {})) def _has_onchange(self, field, other_fields): """ Return whether ``field`` should trigger an onchange event in the diff --git a/odoo/modules/registry.py b/odoo/modules/registry.py index c4bc64adfe2..ec07606d6f9 100644 --- a/odoo/modules/registry.py +++ b/odoo/modules/registry.py @@ -261,16 +261,23 @@ class Registry(Mapping): for model in models: model._setup_fields() + for model in models: + model._setup_complete() + + self.registry_invalidated = True + + @lazy_property + def field_triggers(self): # determine field dependencies dependencies = {} - for model in models: - if model._abstract: + for Model in self.models.values(): + if Model._abstract: continue - for field in model._fields.values(): + for field in Model._fields.values(): # dependencies of custom fields may not exist; ignore that case exceptions = (Exception,) if field.base_field.manual else () with ignore(*exceptions): - dependencies[field] = set(field.resolve_depends(model)) + dependencies[field] = set(field.resolve_depends(self)) # determine transitive dependencies def transitive_dependencies(field, seen=[]): @@ -299,10 +306,7 @@ class Registry(Mapping): tree = tree.setdefault(label, {}) tree.setdefault(None, set()).add(field) - self.field_triggers = triggers - - for model in models: - model._setup_complete() + return triggers def post_init(self, func, *args, **kwargs): """ Register a function to call at the end of :meth:`~.init_models`. """ |
