[FIX] ir_models: fix registry when we add/remove/modify a custom model/field
This commit is contained in:
parent
9696d76aec
commit
24f26c0eeb
|
@ -26,9 +26,9 @@ import time
|
|||
import types
|
||||
|
||||
import openerp
|
||||
import openerp.modules.registry
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp import tools
|
||||
from openerp import models, tools
|
||||
from openerp.modules.registry import RegistryManager
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.osv.orm import BaseModel, Model, MAGIC_COLUMNS, except_orm
|
||||
from openerp.tools import config
|
||||
|
@ -181,8 +181,8 @@ class ir_model(osv.osv):
|
|||
# only reload pool for normal unlink. For module uninstall the
|
||||
# reload is done independently in openerp.modules.loading
|
||||
cr.commit() # must be committed before reloading registry in new cursor
|
||||
openerp.modules.registry.RegistryManager.new(cr.dbname)
|
||||
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
|
||||
RegistryManager.new(cr.dbname)
|
||||
RegistryManager.signal_registry_change(cr.dbname)
|
||||
|
||||
return res
|
||||
|
||||
|
@ -205,8 +205,6 @@ class ir_model(osv.osv):
|
|||
if vals.get('state','base')=='manual':
|
||||
self.instanciate(cr, user, vals['model'], context)
|
||||
model = self.pool[vals['model']]
|
||||
model._prepare_setup_fields(cr, SUPERUSER_ID)
|
||||
model._setup_fields(cr, SUPERUSER_ID)
|
||||
ctx = dict(context,
|
||||
field_name=vals['name'],
|
||||
field_state='manual',
|
||||
|
@ -214,25 +212,25 @@ class ir_model(osv.osv):
|
|||
update_custom_fields=True)
|
||||
model._auto_init(cr, ctx)
|
||||
model._auto_end(cr, ctx) # actually create FKs!
|
||||
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
|
||||
self.pool.setup_models(cr, partial=(not self.pool.ready))
|
||||
RegistryManager.signal_registry_change(cr.dbname)
|
||||
return res
|
||||
|
||||
def instanciate(self, cr, user, model, context=None):
|
||||
class x_custom_model(osv.osv):
|
||||
_custom = True
|
||||
if isinstance(model, unicode):
|
||||
model = model.encode('utf-8')
|
||||
x_custom_model._name = model
|
||||
x_custom_model._module = False
|
||||
a = x_custom_model._build_model(self.pool, cr)
|
||||
if not a._columns:
|
||||
x_name = 'id'
|
||||
elif 'x_name' in a._columns.keys():
|
||||
x_name = 'x_name'
|
||||
else:
|
||||
x_name = a._columns.keys()[0]
|
||||
x_custom_model._rec_name = x_name
|
||||
a._rec_name = x_name
|
||||
|
||||
class CustomModel(models.Model):
|
||||
_name = model
|
||||
_module = False
|
||||
_custom = True
|
||||
|
||||
obj = CustomModel._build_model(self.pool, cr)
|
||||
obj._rec_name = CustomModel._rec_name = (
|
||||
'x_name' if 'x_name' in obj._columns else
|
||||
list(obj._columns)[0] if obj._columns else
|
||||
'id'
|
||||
)
|
||||
|
||||
class ir_model_fields(osv.osv):
|
||||
_name = 'ir.model.fields'
|
||||
|
@ -329,15 +327,15 @@ class ir_model_fields(osv.osv):
|
|||
column_name = cr.fetchone()
|
||||
if column_name and (result and result[0] == 'r'):
|
||||
cr.execute('ALTER table "%s" DROP column "%s" cascade' % (model._table, field.name))
|
||||
model._columns.pop(field.name, None)
|
||||
|
||||
# remove m2m relation table for custom fields
|
||||
# we consider the m2m relation is only one way as it's not possible
|
||||
# to specify the relation table in the interface for custom fields
|
||||
# TODO master: maybe use ir.model.relations for custom fields
|
||||
if field.state == 'manual' and field.ttype == 'many2many':
|
||||
rel_name = self.pool[field.model]._all_columns[field.name].column._rel
|
||||
rel_name = model._fields[field.name].relation
|
||||
cr.execute('DROP table "%s"' % (rel_name))
|
||||
model._pop_field(field.name)
|
||||
|
||||
return True
|
||||
|
||||
def unlink(self, cr, user, ids, context=None):
|
||||
|
@ -353,7 +351,8 @@ class ir_model_fields(osv.osv):
|
|||
res = super(ir_model_fields, self).unlink(cr, user, ids, context)
|
||||
if not context.get(MODULE_UNINSTALL_FLAG):
|
||||
cr.commit()
|
||||
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
|
||||
self.pool.setup_models(cr, partial=(not self.pool.ready))
|
||||
RegistryManager.signal_registry_change(cr.dbname)
|
||||
return res
|
||||
|
||||
def create(self, cr, user, vals, context=None):
|
||||
|
@ -384,10 +383,8 @@ class ir_model_fields(osv.osv):
|
|||
if self.pool.fields_by_model is not None:
|
||||
cr.execute('SELECT * FROM ir_model_fields WHERE id=%s', (res,))
|
||||
self.pool.fields_by_model.setdefault(vals['model'], []).append(cr.dictfetchone())
|
||||
model.__init__(self.pool, cr)
|
||||
model._prepare_setup_fields(cr, SUPERUSER_ID)
|
||||
model._setup_fields(cr, SUPERUSER_ID)
|
||||
|
||||
model.__init__(self.pool, cr)
|
||||
#Added context to _auto_init for special treatment to custom field for select_level
|
||||
ctx = dict(context,
|
||||
field_name=vals['name'],
|
||||
|
@ -396,7 +393,8 @@ class ir_model_fields(osv.osv):
|
|||
update_custom_fields=True)
|
||||
model._auto_init(cr, ctx)
|
||||
model._auto_end(cr, ctx) # actually create FKs!
|
||||
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
|
||||
self.pool.setup_models(cr, partial=(not self.pool.ready))
|
||||
RegistryManager.signal_registry_change(cr.dbname)
|
||||
|
||||
return res
|
||||
|
||||
|
@ -490,11 +488,12 @@ class ir_model_fields(osv.osv):
|
|||
res = super(ir_model_fields,self).write(cr, user, ids, vals, context=context)
|
||||
|
||||
if column_rename:
|
||||
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO "%s"' % column_rename[1])
|
||||
obj, rename = column_rename
|
||||
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO "%s"' % rename)
|
||||
# This is VERY risky, but let us have this feature:
|
||||
# we want to change the key of column in obj._columns dict
|
||||
col = column_rename[0]._columns.pop(column_rename[1][1]) # take object out, w/o copy
|
||||
column_rename[0]._columns[column_rename[1][2]] = col
|
||||
# we want to change the key of field in obj._fields and obj._columns
|
||||
field = obj._pop_field(rename[1])
|
||||
obj._add_field(rename[2], field)
|
||||
|
||||
if models_patch:
|
||||
# We have to update _columns of the model(s) and then call their
|
||||
|
@ -507,11 +506,16 @@ class ir_model_fields(osv.osv):
|
|||
|
||||
for __, patch_struct in models_patch.items():
|
||||
obj = patch_struct[0]
|
||||
# TODO: update new-style fields accordingly
|
||||
for col_name, col_prop, val in patch_struct[1]:
|
||||
setattr(obj._columns[col_name], col_prop, val)
|
||||
obj._auto_init(cr, ctx)
|
||||
obj._auto_end(cr, ctx) # actually create FKs!
|
||||
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
|
||||
|
||||
if column_rename or models_patch:
|
||||
self.pool.setup_models(cr, partial=(not self.pool.ready))
|
||||
RegistryManager.signal_registry_change(cr.dbname)
|
||||
|
||||
return res
|
||||
|
||||
class ir_model_constraint(Model):
|
||||
|
|
|
@ -478,6 +478,18 @@ class BaseModel(object):
|
|||
# remove potential column that may be overridden by field
|
||||
cls._columns.pop(name, None)
|
||||
|
||||
@classmethod
|
||||
def _pop_field(cls, name):
|
||||
""" Remove the field with the given `name` from the model.
|
||||
This method should only be used for manual fields.
|
||||
"""
|
||||
field = cls._fields.pop(name)
|
||||
cls._columns.pop(name, None)
|
||||
cls._all_columns.pop(name, None)
|
||||
if hasattr(cls, name):
|
||||
delattr(cls, name)
|
||||
return field
|
||||
|
||||
@classmethod
|
||||
def _add_magic_fields(cls):
|
||||
""" Introduce magic fields on the current class
|
||||
|
|
Loading…
Reference in New Issue