diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index c3d6a1b4782..ccc1d740403 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -55,7 +55,7 @@ def _symbol_set(symb): class _column(object): """ Base of all fields, a database column - + An instance of this object is a *description* of a database column. It will not hold any data, but only provide the methods to manipulate data of an ORM record or even prepare/update the database to hold such a field of data. @@ -1295,7 +1295,7 @@ class property(function): def _fnct_read(self, obj, cr, uid, ids, prop_names, obj_dest, context=None): prop = obj.pool.get('ir.property') - # get the default values (for res_id = False) for the property fields + # get the default values (for res_id = False) for the property fields default_val = self._get_defaults(obj, cr, uid, prop_names, context) # build the dictionary that will be returned @@ -1417,12 +1417,16 @@ class column_info(object): :attr parent_column: the name of the column containing the m2o relationship to the parent model that contains this column, None for local columns. + :attr original_parent: if the column is inherited, name of the original + parent model that contains it i.e in case of multilevel + inheritence, None for local columns. """ - def __init__(self, name, column, parent_model=None, parent_column=None): + def __init__(self, name, column, parent_model=None, parent_column=None, original_parent=None): self.name = name self.column = column self.parent_model = parent_model self.parent_column = parent_column + self.original_parent = original_parent # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 07c71809ae6..671a47eac69 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -605,13 +605,13 @@ class orm_template(object): # { 'parent_model': 'm2o_field', ... } _inherits = {} - # Mapping from inherits'd field name to triple (m, r, f) - # where m is the model from which it is inherits'd, - # r is the (local) field towards m, - # and f is the _column object itself. - # example: - # { 'field_name': ('parent_model', 'm2o_field_to_reach_parent' , - # field_column_obj), ... } + # Mapping from inherits'd field name to triple (m, r, f, n) where m is the + # model from which it is inherits'd, r is the (local) field towards m, f + # is the _column object itself, and n is the original (i.e. top-most) + # parent model. + # Example: + # { 'field_name': ('parent_model', 'm2o_field_to_reach_parent', + # field_column_obj, origina_parent_model), ... } _inherit_fields = {} # Mapping field name/column_info object @@ -2664,20 +2664,22 @@ class orm(orm_template): del d['id'] return data - def _inherits_join_add(self, parent_model_name, query): + def _inherits_join_add(self, current_table, parent_model_name, query): """ Add missing table SELECT and JOIN clause to ``query`` for reaching the parent table (no duplicates) - + :param current_table: current model object :param parent_model_name: name of the parent model for which the clauses should be added :param query: query object on which the JOIN should be added """ - inherits_field = self._inherits[parent_model_name] + inherits_field = current_table._inherits[parent_model_name] parent_model = self.pool.get(parent_model_name) parent_table_name = parent_model._table quoted_parent_table_name = '"%s"' % parent_table_name if quoted_parent_table_name not in query.tables: query.tables.append(quoted_parent_table_name) - query.where_clause.append('("%s".%s = %s.id)' % (self._table, inherits_field, parent_table_name)) + query.where_clause.append('(%s.%s = %s.id)' % (current_table._table, inherits_field, parent_table_name)) + + def _inherits_join_calc(self, field, query): """ @@ -2692,7 +2694,7 @@ class orm(orm_template): while field in current_table._inherit_fields and not field in current_table._columns: parent_model_name = current_table._inherit_fields[field][0] parent_table = self.pool.get(parent_model_name) - self._inherits_join_add(parent_model_name, query) + self._inherits_join_add(current_table, parent_model_name, query) current_table = parent_table return '"%s".%s' % (current_table._table, field) @@ -3383,9 +3385,9 @@ class orm(orm_template): for table in self._inherits: other = self.pool.get(table) for col in other._columns.keys(): - res[col] = (table, self._inherits[table], other._columns[col]) + res[col] = (table, self._inherits[table], other._columns[col], table) for col in other._inherit_fields.keys(): - res[col] = (table, self._inherits[table], other._inherit_fields[col][2]) + res[col] = (table, self._inherits[table], other._inherit_fields[col][2], other._inherit_fields[col][3]) self._inherit_fields = res self._all_columns = self._get_column_infos() self._inherits_reload_src() @@ -3396,8 +3398,8 @@ class orm(orm_template): inherited field via _inherits) to a ``column_info`` struct giving detailed columns """ result = {} - for k, (parent, m2o, col) in self._inherit_fields.iteritems(): - result[k] = fields.column_info(k, col, parent, m2o) + for k, (parent, m2o, col, original_parent) in self._inherit_fields.iteritems(): + result[k] = fields.column_info(k, col, parent, m2o, original_parent) for k, col in self._columns.iteritems(): result[k] = fields.column_info(k, col) return result @@ -4106,7 +4108,7 @@ class orm(orm_template): upd_todo = [] for v in vals.keys(): if v in self._inherit_fields: - (table, col, col_detail) = self._inherit_fields[v] + (table, col, col_detail, original_parent) = self._inherit_fields[v] tocreate[table][v] = vals[v] del vals[v] else: @@ -4436,7 +4438,7 @@ class orm(orm_template): if parent_model and child_object: # as inherited rules are being applied, we need to add the missing JOIN # to reach the parent table (if it was not JOINed yet in the query) - child_object._inherits_join_add(parent_model, query) + child_object._inherits_join_add(child_object, parent_model, query) query.where_clause += added_clause query.where_clause_params += added_params for table in added_tables: @@ -4525,7 +4527,7 @@ class orm(orm_template): else: continue # ignore non-readable or "non-joinable" fields elif order_field in self._inherit_fields: - parent_obj = self.pool.get(self._inherit_fields[order_field][0]) + parent_obj = self.pool.get(self._inherit_fields[order_field][3]) order_column = parent_obj._columns[order_field] if order_column._classic_read: inner_clause = self._inherits_join_calc(order_field, query) @@ -4669,9 +4671,13 @@ class orm(orm_template): # force a clean recompute! for parent_column in ['parent_left', 'parent_right']: data.pop(parent_column, None) - - for v in self._inherits: - del data[self._inherits[v]] + # Remove _inherits field's from data recursively, missing parents will + # be created by create() (so that copy() copy everything). + def remove_ids(inherits_dict): + for parent_table in inherits_dict: + del data[inherits_dict[parent_table]] + remove_ids(self.pool.get(parent_table)._inherits) + remove_ids(self._inherits) return data def copy_translations(self, cr, uid, old_id, new_id, context=None):