openerp-india team mailing list archive
-
openerp-india team
-
Mailing list archive
-
Message #13111
[Bug 1018908] [NEW] fields.function stored with multi argument and mixed integer/manyone types
Public bug reported:
This is quite a tricky bug that requires 2 fields.function stored in
database, linked with a 'multi' argument and of two different types:
integer and many2one. Something like that:
_columns = {
'm2o_field_id': fields.function(_get_infos, method=True, type='many2one', relation='some.object', string='some string', store=True),
'integer_field': fields.function(_get_infos, method=True, type='integer', string='some other string', store=True),
}
Lets say, _store_set_values(self, cr, uid, ids, fields, context):" is
called with fields= ['m2o_field_id', 'integer_field'], ids = [my_id]
in orm.py, line 3824, you have:
todo = {}
keys = []
for f in fields:
if self._columns[f]._multi not in keys:
keys.append(self._columns[f]._multi)
todo.setdefault(self._columns[f]._multi, [])
todo[self._columns[f]._multi].append(f)
for key in keys:
val = todo[key]
if key:
# uid == 1 for accessing objects having rules defined on store fields
result = self._columns[val[0]].get(cr, self, ids, val, 1, context=context)
so val will contain either ['m2o_field_id', 'integer_field'] or
['integer_field', 'm2o_field_id'] depending on the order they are called
and the fields.get function will be called with val[0] which is either
an integer field or a many2one field.
Now if you go to the get function of fields.function, you have this type of code:
fields.py, line 817
if self._type == "many2one" :
# Filtering only integer/long values if passed
res_ids = [x for x in res.values() if x and isinstance(x, (int,long))]
if res_ids:
obj_model = obj.pool.get(self._obj)
dict_names = dict(obj_model.name_get(cr, user, res_ids, context))
for r in res.keys():
if res[r] and res[r] in dict_names:
res[r] = (res[r], dict_names[res[r]])
if self._type == "integer":
for r in res.keys():
# Converting value into string so that it does not affect XML-RPC Limits
if isinstance(res[r],dict): # To treat integer values with _multi attribute
for record in res[r].keys():
res[r][record] = str(res[r][record])
else:
res[r] = str(res[r])
Either way, the function _get_infos will return something like that:
{my_id:{
'integer_field': 200,
'm2o_field_id': 42,
}}
but the result in _store_set_values will have either (depending on the order):
- if val[0] is a many2one:
result ={my_id:{
'integer_field': 200,
'm2o_field_id': 42,
}} (no_action)
or
- if val[0] is an integer:
result ={my_id:{
'integer_field': '200',
'm2o_field_id': '42',
}} (integer field transforms into string)
And in _store_set_values, you have:
in orm.py, line 3834
for id, value in result.items():
#some code
for v in value:
if v not in val:
continue
if self._columns[v]._type in ('many2one', 'one2one'):
try:
value[v] = value[v][0]
except:
pass
So we will store either:
{
'integer_field': 200,
'm2o_field_id': 42,
} => OK
or
{
'integer_field': '200',
'm2o_field_id': '4', #instead of 42
} => KO
depending on the order...
server 6.0, revno 3626
** Affects: openobject-server
Importance: Undecided
Status: New
** Description changed:
- This is quite a tricky bug that 2 fields.function stored in database,
- linked with a 'multi' argument and of two different types: integer and
- many2one. Something like that:
+ This is quite a tricky bug that requires 2 fields.function stored in
+ database, linked with a 'multi' argument and of two different types:
+ integer and many2one. Something like that:
_columns = {
- 'm2o_field_id': fields.function(_get_infos, method=True, type='many2one', relation='some.object', string='some string', store=True),
- 'integer_field': fields.function(_get_infos, method=True, type='integer', string='some other string', store=True),
+ 'm2o_field_id': fields.function(_get_infos, method=True, type='many2one', relation='some.object', string='some string', store=True),
+ 'integer_field': fields.function(_get_infos, method=True, type='integer', string='some other string', store=True),
}
Lets say, _store_set_values(self, cr, uid, ids, fields, context):" is
called with fields= ['m2o_field_id', 'integer_field'], ids = [my_id]
in orm.py, line 3824, you have:
- todo = {}
- keys = []
- for f in fields:
- if self._columns[f]._multi not in keys:
- keys.append(self._columns[f]._multi)
- todo.setdefault(self._columns[f]._multi, [])
- todo[self._columns[f]._multi].append(f)
- for key in keys:
- val = todo[key]
- if key:
- # uid == 1 for accessing objects having rules defined on store fields
- result = self._columns[val[0]].get(cr, self, ids, val, 1, context=context)
+ todo = {}
+ keys = []
+ for f in fields:
+ if self._columns[f]._multi not in keys:
+ keys.append(self._columns[f]._multi)
+ todo.setdefault(self._columns[f]._multi, [])
+ todo[self._columns[f]._multi].append(f)
+ for key in keys:
+ val = todo[key]
+ if key:
+ # uid == 1 for accessing objects having rules defined on store fields
+ result = self._columns[val[0]].get(cr, self, ids, val, 1, context=context)
so val will contain either ['m2o_field_id', 'integer_field'] or
['integer_field', 'm2o_field_id'] depending on the order they are called
and the fields.get function will be called with val[0] which is either
an integer field or a many2one field.
Now if you go to the get function of fields.function, you have this type of code:
- fields.py, line 817
- if self._type == "many2one" :
- # Filtering only integer/long values if passed
- res_ids = [x for x in res.values() if x and isinstance(x, (int,long))]
+ fields.py, line 817
+ if self._type == "many2one" :
+ # Filtering only integer/long values if passed
+ res_ids = [x for x in res.values() if x and isinstance(x, (int,long))]
- if res_ids:
- obj_model = obj.pool.get(self._obj)
- dict_names = dict(obj_model.name_get(cr, user, res_ids, context))
- for r in res.keys():
- if res[r] and res[r] in dict_names:
- res[r] = (res[r], dict_names[res[r]])
+ if res_ids:
+ obj_model = obj.pool.get(self._obj)
+ dict_names = dict(obj_model.name_get(cr, user, res_ids, context))
+ for r in res.keys():
+ if res[r] and res[r] in dict_names:
+ res[r] = (res[r], dict_names[res[r]])
- if self._type == "integer":
- for r in res.keys():
- # Converting value into string so that it does not affect XML-RPC Limits
- if isinstance(res[r],dict): # To treat integer values with _multi attribute
- for record in res[r].keys():
- res[r][record] = str(res[r][record])
- else:
- res[r] = str(res[r])
+ if self._type == "integer":
+ for r in res.keys():
+ # Converting value into string so that it does not affect XML-RPC Limits
+ if isinstance(res[r],dict): # To treat integer values with _multi attribute
+ for record in res[r].keys():
+ res[r][record] = str(res[r][record])
+ else:
+ res[r] = str(res[r])
Either way, the function _get_infos will return something like that:
{my_id:{
'integer_field': 200,
'm2o_field_id': 42,
}}
but the result in _store_set_values will have either (depending on the order):
- if val[0] is a many2one:
result ={my_id:{
'integer_field': 200,
'm2o_field_id': 42,
}} (no_action)
or
- if val[0] is an integer:
result ={my_id:{
'integer_field': '200',
'm2o_field_id': '42',
}} (integer field transforms into string)
And in _store_set_values, you have:
in orm.py, line 3834
for id, value in result.items():
#some code
- for v in value:
- if v not in val:
- continue
- if self._columns[v]._type in ('many2one', 'one2one'):
- try:
- value[v] = value[v][0]
- except:
- pass
+ for v in value:
+ if v not in val:
+ continue
+ if self._columns[v]._type in ('many2one', 'one2one'):
+ try:
+ value[v] = value[v][0]
+ except:
+ pass
So we will store either:
{
'integer_field': 200,
'm2o_field_id': 42,
} => OK
or
{
'integer_field': '200',
'm2o_field_id': '4', #instead of 42
} => KO
depending on the order...
server 6.0, revno 3626
--
You received this bug notification because you are a member of OpenERP
Indian Team, which is subscribed to OpenERP Server.
https://bugs.launchpad.net/bugs/1018908
Title:
fields.function stored with multi argument and mixed integer/manyone
types
Status in OpenERP Server:
New
Bug description:
This is quite a tricky bug that requires 2 fields.function stored in
database, linked with a 'multi' argument and of two different types:
integer and many2one. Something like that:
_columns = {
'm2o_field_id': fields.function(_get_infos, method=True, type='many2one', relation='some.object', string='some string', store=True),
'integer_field': fields.function(_get_infos, method=True, type='integer', string='some other string', store=True),
}
Lets say, _store_set_values(self, cr, uid, ids, fields, context):" is
called with fields= ['m2o_field_id', 'integer_field'], ids = [my_id]
in orm.py, line 3824, you have:
todo = {}
keys = []
for f in fields:
if self._columns[f]._multi not in keys:
keys.append(self._columns[f]._multi)
todo.setdefault(self._columns[f]._multi, [])
todo[self._columns[f]._multi].append(f)
for key in keys:
val = todo[key]
if key:
# uid == 1 for accessing objects having rules defined on store fields
result = self._columns[val[0]].get(cr, self, ids, val, 1, context=context)
so val will contain either ['m2o_field_id', 'integer_field'] or
['integer_field', 'm2o_field_id'] depending on the order they are
called
and the fields.get function will be called with val[0] which is either
an integer field or a many2one field.
Now if you go to the get function of fields.function, you have this type of code:
fields.py, line 817
if self._type == "many2one" :
# Filtering only integer/long values if passed
res_ids = [x for x in res.values() if x and isinstance(x, (int,long))]
if res_ids:
obj_model = obj.pool.get(self._obj)
dict_names = dict(obj_model.name_get(cr, user, res_ids, context))
for r in res.keys():
if res[r] and res[r] in dict_names:
res[r] = (res[r], dict_names[res[r]])
if self._type == "integer":
for r in res.keys():
# Converting value into string so that it does not affect XML-RPC Limits
if isinstance(res[r],dict): # To treat integer values with _multi attribute
for record in res[r].keys():
res[r][record] = str(res[r][record])
else:
res[r] = str(res[r])
Either way, the function _get_infos will return something like that:
{my_id:{
'integer_field': 200,
'm2o_field_id': 42,
}}
but the result in _store_set_values will have either (depending on the order):
- if val[0] is a many2one:
result ={my_id:{
'integer_field': 200,
'm2o_field_id': 42,
}} (no_action)
or
- if val[0] is an integer:
result ={my_id:{
'integer_field': '200',
'm2o_field_id': '42',
}} (integer field transforms into string)
And in _store_set_values, you have:
in orm.py, line 3834
for id, value in result.items():
#some code
for v in value:
if v not in val:
continue
if self._columns[v]._type in ('many2one', 'one2one'):
try:
value[v] = value[v][0]
except:
pass
So we will store either:
{
'integer_field': 200,
'm2o_field_id': 42,
} => OK
or
{
'integer_field': '200',
'm2o_field_id': '4', #instead of 42
} => KO
depending on the order...
server 6.0, revno 3626
To manage notifications about this bug go to:
https://bugs.launchpad.net/openobject-server/+bug/1018908/+subscriptions
Follow ups
References