[FIX] ir_model: field names must be valid pg identifiers

This commit is contained in:
Raphael Collet
2017-04-06 15:05:52 +02:00
committed by Raphael Collet
parent e79d94438e
commit 6b48098c81
3 changed files with 72 additions and 7 deletions
+6
View File
@@ -7370,6 +7370,12 @@ msgstr ""
msgid "Field `%(field_name)s` does not exist"
msgstr ""
#. module: base
#: code:addons/base/ir/ir_model.py:298
#, python-format
msgid "Field names can only contain characters, digits and underscores (up to 63)."
msgstr ""
#. module: base
#: model:ir.actions.act_window,name:base.action_model_fields
#: model:ir.model,name:base.model_ir_model_fields
+11 -7
View File
@@ -286,6 +286,17 @@ class IrModelFields(models.Model):
raise UserError(_("The Selection Options expression is not a valid Pythonic expression."
"Please provide an expression in the [('key','Label'), ...] format."))
@api.constrains('name', 'state')
def _check_name(self):
for field in self:
if field.state == 'manual' and not field.name.startswith('x_'):
raise ValidationError(_("Custom fields must have a name that starts with 'x_' !"))
try:
models.check_pg_name(field.name)
except ValidationError:
msg = _("Field names can only contain characters, digits and underscores (up to 63).")
raise ValidationError(msg)
_sql_constraints = [
('size_gt_zero', 'CHECK (size>=0)', 'Size of the field cannot be negative.'),
]
@@ -492,9 +503,6 @@ class IrModelFields(models.Model):
res = super(IrModelFields, self).create(vals)
if vals.get('state', 'manual') == 'manual':
if not vals['name'].startswith('x_'):
raise UserError(_("Custom fields must have a name that starts with 'x_' !"))
if vals.get('relation') and not self.env['ir.model'].search([('model', '=', vals['relation'])]):
raise UserError(_("Model %s does not exist!") % vals['relation'])
@@ -559,10 +567,6 @@ class IrModelFields(models.Model):
raise UserError(_('Can only rename one field at a time!'))
if vals['name'] in obj._fields:
raise UserError(_('Cannot rename field to %s, because that field already exists!') % vals['name'])
if vals.get('state', 'manual') == 'manual' and not vals['name'].startswith('x_'):
raise UserError(_('New field name must still start with x_ , because it is a custom field!'))
if '\'' in vals['name'] or '"' in vals['name'] or ';' in vals['name']:
raise ValueError('Invalid character in column name')
column_rename = (obj._table, item.name, vals['name'], item.index)
# We don't check the 'state', because it might come from the context
+55
View File
@@ -368,3 +368,58 @@ class TestServerActions(TestServerActionsBase):
self.action.write({
'child_ids': [(6, 0, [self.action.id])]
})
class TestCustomFields(common.TransactionCase):
MODEL = 'res.partner'
def setUp(self):
# use a test cursor instead of a real cursor
registry = odoo.registry()
registry.enter_test_mode()
fnames = set(registry[self.MODEL]._fields)
@self.addCleanup
def callback():
registry.leave_test_mode()
# the tests may have modified the registry, reset it
with registry.cursor() as cr:
registry.clear_manual_fields()
registry.setup_models(cr)
assert set(registry[self.MODEL]._fields) == fnames
super(TestCustomFields, self).setUp()
def create_field(self, name):
""" create a custom field and return it """
model = self.env['ir.model'].search([('model', '=', self.MODEL)])
field = self.env['ir.model.fields'].create({
'model_id': model.id,
'name': name,
'field_description': name,
'ttype': 'char',
})
self.assertIn(name, self.env[self.MODEL]._fields)
return field
def test_create_custom(self):
""" custom field names must be start with 'x_' """
with self.assertRaises(ValidationError):
self.create_field('foo')
def test_rename_custom(self):
""" custom field names must be start with 'x_' """
field = self.create_field('x_foo')
with self.assertRaises(ValidationError):
field.name = 'foo'
def test_create_valid(self):
""" field names must be valid pg identifiers """
with self.assertRaises(ValidationError):
self.create_field('x_foo bar')
def test_rename_valid(self):
""" field names must be valid pg identifiers """
field = self.create_field('x_foo')
with self.assertRaises(ValidationError):
field.name = 'x_foo bar'