[ADD] ir_model: add fields copy and related on ir.model.fields

Also add a constraint on the value of field `related`, and corresponding
onchange methods.
This commit is contained in:
Raphael Collet
2015-08-18 14:53:04 +02:00
parent 78577a606d
commit d1927bb746
4 changed files with 47 additions and 0 deletions
+2
View File
@@ -35,6 +35,8 @@ CREATE TABLE ir_model_fields (
relation varchar,
relation_field varchar,
select_level varchar,
copy boolean,
related varchar,
readonly boolean default False,
required boolean default False,
selectable boolean default False,
+37
View File
@@ -226,6 +226,8 @@ class ir_model_fields(osv.osv):
'selection': fields.char('Selection Options', help="List of options for a selection field, "
"specified as a Python expression defining a list of (key, label) pairs. "
"For example: [('blue','Blue'),('yellow','Yellow')]"),
'copy': fields.boolean('Copied', help="Whether the value is copied when duplicating a record."),
'related': fields.char('Related Field', help="The corresponding related field, if any. This must be a dot-separated list of field names."),
'required': fields.boolean('Required'),
'readonly': fields.boolean('Readonly'),
'select_level': fields.selection([('0','Not Searchable'),('1','Always Searchable'),('2','Advanced Search (deprecated)')],'Searchable', required=True),
@@ -290,6 +292,40 @@ class ir_model_fields(osv.osv):
('size_gt_zero', 'CHECK (size>=0)',_size_gt_zero_msg ),
]
def _related_field(self):
""" Return the ``Field`` instance corresponding to ``self.related``. """
names = self.related.split(".")
last = len(names) - 1
model = self.env[self.model or self.model_id.model]
for index, name in enumerate(names):
field = model._fields.get(name)
if field is None:
raise UserError(_("Unknown field name '%s' in related field '%s'") % (name, self.related))
if index < last and not field.relational:
raise UserError(_("Non-relational field name '%s' in related field '%s'") % (name, self.related))
model = model[name]
return field
@api.one
@api.constrains('related')
def _check_related(self):
if self.state == 'manual' and self.related:
field = self._related_field()
if field.type != self.ttype:
raise UserError(_("Related field '%s' does not have type '%s'") % (self.related, self.ttype))
if field.relational and field.comodel_name != self.relation:
raise UserError(_("Related field '%s' does not have comodel '%s'") % (self.related, self.relation))
@api.onchange('related')
def _onchange_related(self):
if self.related:
try:
field = self._related_field()
except UserError as e:
return {'warning': {'title': _("Warning"), 'message': e.message}}
self.ttype = field.type
self.relation = field.comodel_name
@api.model
def _custom_many2many_names(self, model_name, comodel_name):
""" Return default names for the table and columns of a custom many2many field. """
@@ -303,6 +339,7 @@ class ir_model_fields(osv.osv):
@api.onchange('ttype', 'model_id', 'relation')
def _onchange_ttype(self):
self.copy = (self.ttype != 'one2many')
if self.ttype == 'many2many' and self.model_id and self.relation:
names = self._custom_many2many_names(self.model_id.model, self.relation)
self.relation_table, self.column1, self.column2 = names
+4
View File
@@ -65,6 +65,7 @@
</group>
<group string="Properties">
<group>
<field name="related"/>
<field name="ttype"/>
<field name="relation" attrs="{'required': [('ttype','in',['many2one','one2many','many2many'])],'readonly': [('ttype','!=','one2many'), ('ttype','!=','many2one'), ('ttype','!=','many2many')]}"/>
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')], 'readonly': [('ttype','!=','one2many')]}"/>
@@ -80,6 +81,7 @@
<field name="required"/>
<field name="readonly"/>
<field name="select_level"/>
<field name="copy"/>
<field name="translate"/>
<field name="on_delete" attrs="{'readonly': [('ttype','!=','many2one')]}"/>
<field name="modules"/>
@@ -170,6 +172,7 @@
</group>
<group>
<group>
<field name="related"/>
<field name="ttype"/>
<field name="relation" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],
'readonly': [('ttype','not in', ['many2one','one2many','many2many'])]}"/>
@@ -187,6 +190,7 @@
<field name="required"/>
<field name="readonly"/>
<field name="select_level"/>
<field name="copy"/>
<field name="translate"/>
</group>
</group>
+4
View File
@@ -385,6 +385,8 @@ class BaseModel(object):
'ttype': f.type,
'relation': f.comodel_name or None,
'select_level': tools.ustr(int(f.index)),
'copy': bool(f.copy),
'related': f.related and ".".join(f.related),
'readonly': bool(f.readonly),
'required': bool(f.required),
'selectable': bool(f.search or f.store),
@@ -670,6 +672,8 @@ class BaseModel(object):
attrs = {
'manual': True,
'string': field['field_description'],
'copy': bool(field['copy']),
'related': field['related'],
'required': bool(field['required']),
'readonly': bool(field['readonly']),
}