From ca5fcc2bdfd49920a8d54ef8f361b9571c9b06d2 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 17 Nov 2011 15:30:10 +0100 Subject: [PATCH] [IMP] orm,fields: some cleanup for sparse field implementation (wip) bzr revid: odo@openerp.com-20111117143010-9nv7inr5ijzykgem --- openerp/osv/fields.py | 37 ++++++++++++++++--------------------- openerp/osv/orm.py | 21 ++++++++------------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 04364a63074..222dd4aaeb0 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -1210,23 +1210,23 @@ class sparse(function): """ if self._type == 'many2many': - #NOTE only the option (0, 0, { values }) is supported for many2many - if value[0][0] == 6: - return value[0][2] - + assert value[0][0] == 6, 'Unsupported m2m value for sparse field: %s' % value + return value[0][2] + elif self._type == 'one2many': if not read_value: - read_value=[] + read_value = [] relation_obj = obj.pool.get(self.relation) for vals in value: + assert vals[0] in (0,1,2), 'Unsupported o2m value for sparse field: %s' % vals if vals[0] == 0: read_value.append(relation_obj.create(cr, uid, vals[2], context=context)) elif vals[0] == 1: relation_obj.write(cr, uid, vals[1], vals[2], context=context) elif vals[0] == 2: - relation_obj.unlink(cr, uid, vals[1]) + relation_obj.unlink(cr, uid, vals[1], context=context) read_value.remove(vals[1]) - return read_value + return read_value return value @@ -1236,37 +1236,32 @@ class sparse(function): records = obj.browse(cr, uid, ids, context=context) for record in records: # grab serialized value as object - already deserialized - serialized = record.__getattr__(self.serialization_field) - # we have to delete the key in the json when the value is null + serialized = getattr(record, self.serialization_field) if value is None: - if field_name in serialized: - del serialized[field_name] - else: - # nothing to do, we dont wan't to store the key with a null value - continue + # simply delete the key to unset it. + serialized.pop(field_name, None) else: serialized[field_name] = self.convert_value(obj, cr, uid, record, value, serialized.get(field_name), context=context) obj.write(cr, uid, ids, {self.serialization_field: serialized}, context=context) return True def _fnct_read(self, obj, cr, uid, ids, field_names, args, context=None): - results={} + results = {} records = obj.browse(cr, uid, ids, context=context) for record in records: # grab serialized value as object - already deserialized - serialized = record.__getattr__(self.serialization_field) - results[record.id] ={} + serialized = getattr(record, self.serialization_field) + results[record.id] = {} for field_name in field_names: if obj._columns[field_name]._type in ['one2many']: - results[record.id].update({field_name : serialized.get(field_name, [])}) + value = serialized.get(field_name, []) else: - results[record.id].update({field_name : serialized.get(field_name)}) + results[record.id].update(field_name=value) return results def __init__(self, serialization_field, **kwargs): self.serialization_field = serialization_field - #assert serialization_field._type == 'serialized' - return super(sparse, self).__init__(self._fnct_read, fnct_inv=self._fnct_write, multi='_json_multi', method=True, **kwargs) + return super(sparse, self).__init__(self._fnct_read, fnct_inv=self._fnct_write, multi='__sparse_multi', method=True, **kwargs) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 357204bd374..a004ef96321 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -756,16 +756,10 @@ class BaseModel(object): cols[rec['name']] = rec ir_model_fields_obj = self.pool.get('ir.model.fields') - - high_priority_items=[] - low_priority_items=[] - #sparse field should be created at the end, indeed this field depend of other field - for item in self._columns.items(): - if item[1].__class__ == fields.sparse: - low_priority_items.append(item) - else: - high_priority_items.append(item) - for (k, f) in high_priority_items + low_priority_items: + + # sparse field should be created at the end, as it depends on its serialized field already existing + fields = sorted(self._columns.items(), key=lambda x: 1 if x[1]._type == 'sparse' else 0) + for (k, f) in fields: vals = { 'model_id': model_id, 'model': self._name, @@ -782,12 +776,13 @@ class BaseModel(object): 'relation_field': (f._type=='one2many' and isinstance(f, fields.one2many)) and f._fields_id or '', 'serialization_field_id': None, } - if 'serialization_field' in dir(f): + if getattr(f, 'serialization_field', None): + # resolve link to serialization_field if specified by name serialization_field_id = ir_model_fields_obj.search(cr, 1, [('model','=',vals['model']), ('name', '=', f.serialization_field)]) if not serialization_field_id: - raise except_orm(_('Error'), _("The field %s does not exist!" %f.serialization_field)) + raise except_orm(_('Error'), _("Serialization field `%s` not found for sparse field `%s`!") % (f.serialization_field, k)) vals['serialization_field_id'] = serialization_field_id[0] - + # When its a custom field,it does not contain f.select if context.get('field_state', 'base') == 'manual': if context.get('field_name', '') == k: