[FIX] base: prevent deletion of custom fields when other fields depend on them (#13978)
Consider that you have a custom one2many field based on a custom many2one field, and that you delete the many2one field. From that point on, it is impossible to load the registry of the corresponding database. To prevent this from happening, we add a check before modifying or deleting custom fields.
This commit is contained in:
@@ -142,6 +142,10 @@ class ir_model(osv.osv):
|
||||
if model.state != 'manual':
|
||||
raise UserError(_("Model '%s' contains module data and cannot be removed!") % (model.name,))
|
||||
|
||||
# prevent screwing up fields that depend on these models' fields
|
||||
for model in self.browse(cr, user, ids, context=context):
|
||||
model.field_id._prepare_update()
|
||||
|
||||
self._drop_table(cr, user, ids, context)
|
||||
res = super(ir_model, self).unlink(cr, user, ids, context)
|
||||
if not context.get(MODULE_UNINSTALL_FLAG):
|
||||
@@ -431,6 +435,19 @@ class ir_model_fields(osv.osv):
|
||||
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _prepare_update(self):
|
||||
""" Check whether the fields in ``self`` may be modified or removed.
|
||||
This method prevents the modification/deletion of many2one fields
|
||||
that have an inverse one2many, for instance.
|
||||
"""
|
||||
for record in self:
|
||||
model = self.env[record.model]
|
||||
field = model._fields[record.name]
|
||||
if field.type == 'many2one' and model._field_inverses.get(field):
|
||||
msg = _("The field '%s' cannot be removed because the field '%s' depends on it.")
|
||||
raise UserError(msg % (field, model._field_inverses[field][0]))
|
||||
|
||||
def unlink(self, cr, user, ids, context=None):
|
||||
# Prevent manual deletion of module columns
|
||||
if context is None: context = {}
|
||||
@@ -440,6 +457,9 @@ class ir_model_fields(osv.osv):
|
||||
any(field.state != 'manual' for field in self.browse(cr, user, ids, context)):
|
||||
raise UserError(_("This column contains module data and cannot be removed!"))
|
||||
|
||||
# prevent screwing up fields that depend on these fields
|
||||
self.browse(cr, user, ids, context=context)._prepare_update()
|
||||
|
||||
self._drop_column(cr, user, ids, context)
|
||||
res = super(ir_model_fields, self).unlink(cr, user, ids, context)
|
||||
if not context.get(MODULE_UNINSTALL_FLAG):
|
||||
@@ -528,6 +548,7 @@ class ir_model_fields(osv.osv):
|
||||
|
||||
if vals.get('name', item.name) != item.name:
|
||||
# We need to rename the column
|
||||
item._prepare_update()
|
||||
if column_rename:
|
||||
raise UserError(_('Can only rename one field at a time!'))
|
||||
if vals['name'] in obj._fields:
|
||||
|
||||
Reference in New Issue
Block a user