[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:
Raphael Collet
2016-10-26 14:25:17 +02:00
committed by GitHub
parent 69c41c7e3c
commit ea9ef7c39d
+21
View File
@@ -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: