diff --git a/openerp/fields.py b/openerp/fields.py index df1433087cb..9165ddfde1f 100644 --- a/openerp/fields.py +++ b/openerp/fields.py @@ -289,14 +289,9 @@ class Field(object): self._attrs = {key: val for key, val in kwargs.iteritems() if val is not None} self._free_attrs = [] - def copy(self, **kwargs): - """ copy(item) -> test - - make a copy of `self`, possibly modified with parameters `kwargs` """ - field = copy(self) - field._attrs = {key: val for key, val in kwargs.iteritems() if val is not None} - field._free_attrs = list(self._free_attrs) - return field + def new(self, **kwargs): + """ Return a field of the same type as `self`, with its own parameters. """ + return type(self)(**kwargs) def set_class_name(self, cls, name): """ Assign the model class and field name of `self`. """ @@ -434,12 +429,17 @@ class Field(object): if isinstance(self.related, basestring): self.related = tuple(self.related.split('.')) - # determine the related field, and make sure it is set up + # determine the chain of fields, and make sure they are all set up + fields = [] recs = env[self.model_name] - for name in self.related[:-1]: + for name in self.related: + fields.append(recs._fields[name]) recs = recs[name] - field = self.related_field = recs._fields[self.related[-1]] - field.setup(env) + + for field in fields: + field.setup(env) + + self.related_field = field = fields[-1] # check type consistency if self.type != field.type: @@ -458,6 +458,10 @@ class Field(object): if not getattr(self, attr): setattr(self, attr, getattr(field, prop)) + # special case: required + if not self.required: + self.required = all(field.required for field in fields) + def _compute_related(self, records): """ Compute the related field `self` on `records`. """ # when related_sudo, bypass access rights checks when reading values @@ -486,6 +490,7 @@ class Field(object): return [('.'.join(self.related), operator, value)] # properties used by _setup_related() to copy values from related field + _related_comodel_name = property(attrgetter('comodel_name')) _related_string = property(attrgetter('string')) _related_help = property(attrgetter('help')) _related_readonly = property(attrgetter('readonly')) @@ -1354,6 +1359,17 @@ class _Relational(Field): assert self.comodel_name in env.registry, \ "Field %s with unknown comodel_name %r" % (self, self.comodel_name) + @property + def _related_domain(self): + if callable(self.domain): + # will be called with another model than self's + return lambda recs: self.domain(recs.env[self.model_name]) + else: + # maybe not correct if domain is a string... + return self.domain + + _related_context = property(attrgetter('context')) + _description_relation = property(attrgetter('comodel_name')) _description_context = property(attrgetter('context')) diff --git a/openerp/models.py b/openerp/models.py index 2562e108410..bb54260e5fe 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -811,7 +811,7 @@ class BaseModel(object): cls._fields = {} for attr, field in getmembers(cls, Field.__instancecheck__): if not field.inherited: - cls._add_field(attr, field.copy()) + cls._add_field(attr, field.new()) # introduce magic fields cls._add_magic_fields() @@ -2914,7 +2914,7 @@ class BaseModel(object): 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.copy( + cls._add_field(attr, field.new( inherited=True, related=(parent_field, attr), related_sudo=False,