Improvements to create new fields
bzr revid: fp@tinyerp.com-faf11289ef9e3d081f76861d5800c6cb62d8623e
This commit is contained in:
parent
4f7fb469a5
commit
37a4fe5955
|
@ -195,7 +195,7 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
|||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s' % m)
|
||||
sys.stdout.flush()
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
modules = pool.instanciate(m)
|
||||
modules = pool.instanciate(m, cr)
|
||||
cr.execute('select state, demo from ir_module_module where name=%s', (m,))
|
||||
(package_state, package_demo) = (cr.rowcount and cr.fetchone()) or ('uninstalled', False)
|
||||
idref = {}
|
||||
|
|
|
@ -59,6 +59,7 @@ CREATE TABLE ir_model_fields (
|
|||
field_description varchar(256),
|
||||
ttype varchar(64),
|
||||
group_name varchar(64),
|
||||
state varchar(64) default 'base',
|
||||
view_load boolean,
|
||||
relate boolean default False,
|
||||
primary key(id)
|
||||
|
|
|
@ -709,12 +709,23 @@
|
|||
<separator string="Information" colspan="4"/>
|
||||
<field name="info" select="1" colspan="4" nolabel="1"/>
|
||||
<separator string="Fields" colspan="4"/>
|
||||
<field name="field_id" colspan="4" nolabel="1" readonly="1">
|
||||
<field name="field_id" colspan="4" nolabel="1" context="{'manual':True}">
|
||||
<form string="Fields Description">
|
||||
<field name="name" select="1"/>
|
||||
<field name="field_description" select="1" colspan="4"/>
|
||||
<field name="ttype" select="1"/>
|
||||
<field name="relation" select="1"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="field_description" select="1" colspan="4"/>
|
||||
<field name="ttype" select="1"/>
|
||||
<field name="relation" select="1"/>
|
||||
|
||||
<field name="required" select="2"/>
|
||||
<field name="readonly" select="2"/>
|
||||
|
||||
<field name="size" select="1"/>
|
||||
<field name="on_delete" select="1"/>
|
||||
<field name="select" select="2"/>
|
||||
<field name="translate"/>
|
||||
<field name="selection"/>
|
||||
<field name="domain"/>
|
||||
<field name="state" readonly="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</form>
|
||||
|
@ -749,6 +760,17 @@
|
|||
<field name="field_description" select="2" colspan="4"/>
|
||||
<field name="ttype" select="2"/>
|
||||
<field name="relation" select="2"/>
|
||||
|
||||
<field name="required" select="2"/>
|
||||
<field name="readonly" select="2"/>
|
||||
|
||||
<field name="size" select="1"/>
|
||||
<field name="on_delete" select="1"/>
|
||||
<field name="select" select="2"/>
|
||||
<field name="translate"/>
|
||||
<field name="selection"/>
|
||||
<field name="domain"/>
|
||||
<field name="state" readonly="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -770,6 +792,7 @@
|
|||
<field name="name">Objects</field>
|
||||
<field name="res_model">ir.model</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{'manual':True}</field>
|
||||
<field name="view_id" ref="view_model_tree"/>
|
||||
</record>
|
||||
<menuitem name="Administration/Custom/Low Level/Base/Database Structure/Objects" action="action_model_model" id="ir_model_model_menu"/>
|
||||
|
@ -778,6 +801,7 @@
|
|||
<field name="name">Fields</field>
|
||||
<field name="res_model">ir.model.fields</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{'manual':True}</field>
|
||||
<field name="view_id" ref="view_model_fields_tree"/>
|
||||
</record>
|
||||
<menuitem name="Administration/Custom/Low Level/Base/Database Structure/Fields" action="action_model_fields" id="ir_model_model_fields"/>
|
||||
|
|
|
@ -34,6 +34,10 @@ import time
|
|||
import tools
|
||||
import pooler
|
||||
|
||||
def _get_fields_type(self, cr, uid, context=None):
|
||||
cr.execute('select distinct ttype,ttype from ir_model_fields')
|
||||
return cr.fetchall()
|
||||
|
||||
class ir_model(osv.osv):
|
||||
_name = 'ir.model'
|
||||
_rec_name = 'model'
|
||||
|
@ -51,18 +55,24 @@ ir_model()
|
|||
class ir_model_fields(osv.osv):
|
||||
_name = 'ir.model.fields'
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64),
|
||||
'name': fields.char('Name', required=True, size=64, select=1),
|
||||
'model': fields.char('Model Name', size=64, required=True),
|
||||
# on pourrait egalement changer ca en many2one, mais le prob c'est qu'alors faut
|
||||
# faire une jointure a chaque fois qu'on recherche vu que le client ne connait que le nom
|
||||
# de l'objet et pas son id
|
||||
'relation': fields.char('Model Relation', size=64),
|
||||
'model_id': fields.many2one('ir.model', 'Model id', required=True, select=True, ondelete='cascade'),
|
||||
# in fact, this is the field label
|
||||
'field_description': fields.char('Field Description', size=256),
|
||||
'ttype': fields.char('Field Type', size=64),
|
||||
'field_description': fields.char('Field Label', required=True, size=256),
|
||||
'relate': fields.boolean('Click and Relate'),
|
||||
|
||||
'ttype': fields.selection(_get_fields_type, 'Field Type',size=64, required=True),
|
||||
'selection': fields.char('Field Selection',size=128),
|
||||
'required': fields.boolean('Required'),
|
||||
'readonly': fields.boolean('Readonly'),
|
||||
'select': fields.selection([('0','Not Searchable'),('1','Always Searchable'),('2','Advanced Search')],'Searchable', required=True),
|
||||
'translate': fields.boolean('Translate'),
|
||||
'size': fields.integer('Size'),
|
||||
'state': fields.selection([('manual','Custom Field'),('base','Base Field')],'Manualy Created'),
|
||||
'on_delete': fields.selection([('no','Nothing'),('cascade','Cascade'),('set null','Set NULL')], 'On delete', help='On delete property for many2one fields'),
|
||||
'domain': fields.char('Domain', size=256),
|
||||
|
||||
'groups': fields.many2many('res.groups', 'ir_model_fields_group_rel', 'field_id', 'group_id', 'Groups'),
|
||||
'group_name': fields.char('Group Name', size=128),
|
||||
'view_load': fields.boolean('View Auto-Load'),
|
||||
|
@ -70,10 +80,38 @@ class ir_model_fields(osv.osv):
|
|||
_defaults = {
|
||||
'relate': lambda *a: 0,
|
||||
'view_load': lambda *a: 0,
|
||||
'name': lambda *a: 'No Name',
|
||||
'field_description': lambda *a: 'No description available',
|
||||
'selection': lambda *a: "[]",
|
||||
'domain': lambda *a: "[]",
|
||||
'name': lambda *a: 'x_',
|
||||
'state': lambda self,cr,uid,ctx={}: ctx.get('manual',False) and 'manual' or 'base',
|
||||
'on_delete': lambda *a: 'no',
|
||||
'select': lambda *a: '0',
|
||||
'size': lambda *a: 64,
|
||||
'field_description': lambda *a: '',
|
||||
}
|
||||
_order = "id"
|
||||
def unlink(self, cr, user, ids, context=None):
|
||||
for field in self.browse(cr, uid, ids, context):
|
||||
if field.state <> 'manual':
|
||||
raise except_orm('Error', "You can not remove the field '%s' !" %(field.name,))
|
||||
#
|
||||
# MAY BE ADD A ALTER TABLE DROP ?
|
||||
#
|
||||
return super(ir_model_fields, self).unlink(cr, user, ids, context)
|
||||
|
||||
def create(self, cr, user, vals, context=None):
|
||||
if 'model_id' in vals:
|
||||
model_data=self.pool.get('ir.model').read(cr,user,vals['model_id'])
|
||||
vals['model']=model_data['model']
|
||||
if context and context.get('manual',False):
|
||||
vals['state']='manual'
|
||||
res = super(ir_model_fields,self).create(cr, user, vals, context)
|
||||
if vals.get('state','base')=='manual':
|
||||
if not vals['name'].startswith('x_'):
|
||||
raise except_orm('Error', "Custom fields must have a name that starts with 'x_' !")
|
||||
self.pool.get(vals['model']).__init__(self.pool, cr)
|
||||
self.pool.get(vals['model'])._auto_init(cr)
|
||||
return res
|
||||
ir_model_fields()
|
||||
|
||||
class ir_model_access(osv.osv):
|
||||
|
@ -182,8 +220,8 @@ class ir_model_data(osv.osv):
|
|||
'noupdate': lambda *a: False
|
||||
}
|
||||
|
||||
def __init__(self, pool):
|
||||
osv.osv.__init__(self, pool)
|
||||
def __init__(self, pool, cr):
|
||||
osv.osv.__init__(self, pool, cr)
|
||||
self.loads = {}
|
||||
self.doinit = True
|
||||
self.unlink_mark = {}
|
||||
|
|
|
@ -303,7 +303,7 @@ class orm(object):
|
|||
if not cr.rowcount:
|
||||
cr.execute("select id from ir_model where model='%s'" % self._name)
|
||||
model_id = cr.fetchone()[0]
|
||||
cr.execute("INSERT INTO ir_model_fields (model_id, model, name, field_description, ttype, relate,relation,group_name,view_load) VALUES (%d,%s,%s,%s,%s,%s,%s,%s,%s)", (model_id, self._name, k, f.string.replace("'", " "), f._type, (f.relate and 'True') or 'False', f._obj or 'NULL', f.group_name or '', (f.view_load and 'True') or 'False'))
|
||||
cr.execute("INSERT INTO ir_model_fields (model_id, model, name, field_description, ttype, relate,relation,group_name,view_load,state) VALUES (%d,%s,%s,%s,%s,%s,%s,%s,%s,%s)", (model_id, self._name, k, f.string.replace("'", " "), f._type, (f.relate and 'True') or 'False', f._obj or 'NULL', f.group_name or '', (f.view_load and 'True') or 'False', 'base'))
|
||||
else:
|
||||
id, relate = cr.fetchone()
|
||||
if relate != f.relate:
|
||||
|
@ -528,15 +528,37 @@ class orm(object):
|
|||
cr.execute(line2)
|
||||
cr.commit()
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, cr):
|
||||
if not self._table:
|
||||
self._table=self._name.replace('.','_')
|
||||
if not self._description:
|
||||
self._description = self._name
|
||||
for (key,_,msg) in self._sql_constraints:
|
||||
self.pool._sql_error[self._table+'_'+key] = msg
|
||||
|
||||
# if self.__class__.__name__ != 'fake_class':
|
||||
|
||||
# Load manual fields
|
||||
|
||||
cr.execute("select id from ir_model_fields where name=%s and model=%s", ('state','ir.model.fields'))
|
||||
if cr.fetchone():
|
||||
cr.execute('select * from ir_model_fields where model=%s and state=%s', (self._name,'manual'))
|
||||
for field in cr.dictfetchall():
|
||||
if field['name'] in self._columns:
|
||||
continue
|
||||
attrs = {
|
||||
'string': field['field_description'],
|
||||
'required': bool(field['required']),
|
||||
'readonly': bool(field['readonly']),
|
||||
'domain': field['domain'] or None,
|
||||
'size': field['size'],
|
||||
'ondelete': field['on_delete'],
|
||||
'translate': (field['translate']),
|
||||
'select': int(field['select'])
|
||||
}
|
||||
if field['relation']:
|
||||
attrs['relation'] = field['relation']
|
||||
self._columns[field['name']] = getattr(fields, field['ttype'])(**attrs)
|
||||
|
||||
# if self.__class__.__name__ != 'fake_class':
|
||||
self._inherits_reload()
|
||||
if not self._sequence:
|
||||
self._sequence = self._table+'_id_seq'
|
||||
|
@ -544,18 +566,7 @@ class orm(object):
|
|||
assert (k in self._columns) or (k in self._inherit_fields), 'Default function defined in %s but field %s does not exist !' % (self._name, k,)
|
||||
for f in self._columns:
|
||||
self._columns[f].restart()
|
||||
# FIXME: does not work at all
|
||||
# if self._log_access:
|
||||
# self._columns.update({
|
||||
# 'create_uid': fields.many2one('res.users','Creation user',required=True, readonly=True),
|
||||
# 'create_date': fields.datetime('Creation date',required=True, readonly=True),
|
||||
# 'write_uid': fields.many2one('res.users','Last modification by', readonly=True),
|
||||
# 'write_date': fields.datetime('Last modification date', readonly=True),
|
||||
# })
|
||||
# self._defaults.update({
|
||||
# 'create_uid': lambda self,cr,uid,context : uid,
|
||||
# 'create_date': lambda *a : time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
# })
|
||||
|
||||
#
|
||||
# Update objects that uses this one to update their _inherits fields
|
||||
#
|
||||
|
|
|
@ -168,7 +168,7 @@ class osv_pool(netsvc.Service):
|
|||
return obj
|
||||
|
||||
#TODO: pass a list of modules to load
|
||||
def instanciate(self, module):
|
||||
def instanciate(self, module, cr):
|
||||
# print "module list:", module_list
|
||||
# for module in module_list:
|
||||
res = []
|
||||
|
@ -176,7 +176,7 @@ class osv_pool(netsvc.Service):
|
|||
# if module not in self.module_object_list:
|
||||
# print "%s class_list:" % module, class_list
|
||||
for klass in class_list:
|
||||
res.append(klass.createInstance(self, module))
|
||||
res.append(klass.createInstance(self, module, cr))
|
||||
return res
|
||||
# else:
|
||||
# print "skipping module", module
|
||||
|
@ -225,7 +225,7 @@ class osv(orm.orm):
|
|||
# Goal: try to apply inheritancy at the instanciation level and
|
||||
# put objects in the pool var
|
||||
#
|
||||
def createInstance(cls, pool, module):
|
||||
def createInstance(cls, pool, module, cr):
|
||||
# obj = cls()
|
||||
parent_name = hasattr(cls, '_inherit') and cls._inherit
|
||||
if parent_name:
|
||||
|
@ -245,18 +245,17 @@ class osv(orm.orm):
|
|||
name = hasattr(cls,'_name') and cls._name or cls._inherit
|
||||
#name = str(cls)
|
||||
cls = type(name, (cls, parent_class), nattr)
|
||||
|
||||
obj = object.__new__(cls)
|
||||
obj.__init__(pool)
|
||||
obj.__init__(pool, cr)
|
||||
return obj
|
||||
# return object.__new__(cls, pool)
|
||||
createInstance = classmethod(createInstance)
|
||||
|
||||
def __init__(self, pool):
|
||||
def __init__(self, pool, cr):
|
||||
# print "__init__", self._name, pool
|
||||
pool.add(self._name, self)
|
||||
self.pool = pool
|
||||
orm.orm.__init__(self)
|
||||
orm.orm.__init__(self, cr)
|
||||
|
||||
# pooler.get_pool(cr.dbname).add(self._name, self)
|
||||
# print self._name, module
|
||||
|
|
Loading…
Reference in New Issue