diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index b7f47fe6549..4fe3ab8fad7 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -127,6 +127,23 @@ class _column(object): res = obj.read(cr, uid, ids, [name], context=context) return [x[name] for x in res] + def as_display_name(self, cr, uid, obj, value, context=None): + """Converts a field value to a suitable string representation for a record, + e.g. when this field is used as ``rec_name``. + + :param obj: the ``BaseModel`` instance this column belongs to + :param value: a proper value as returned by :py:meth:`~openerp.orm.osv.BaseModel.read` + for this column + """ + # delegated to class method, so a column type A can delegate + # to a column type B. + return self._as_display_name(self, cr, uid, obj, value, context=None) + + @classmethod + def _as_display_name(cls, field, cr, uid, obj, value, context=None): + # This needs to be a class method, in case a column type A as to delegate + # to a column type B. + return tools.ustr(value) # --------------------------------------------------------- # Simple fields @@ -178,6 +195,17 @@ class reference(_column): result[value['id']] = False return result + @classmethod + def _as_display_name(cls, field, cr, uid, obj, value, context=None): + if value: + # reference fields have a 'model,id'-like value, that we need to convert + # to a real name + model_name, res_id = value.split(',') + model = obj.pool.get(model_name) + if model and res_id: + return model.name_get(cr, uid, [res_id], context=context)[0][1] + return tools.ustr(value) + class char(_column): _type = 'char' @@ -453,6 +481,11 @@ class many2one(_column): def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, context=None): return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name', 'like', value)], offset, limit, context=context) + + @classmethod + def _as_display_name(cls, field, cr, uid, obj, value, context=None): + return value[1] if isinstance(value, tuple) else tools.ustr(value) + class one2many(_column): _classic_read = False @@ -543,6 +576,10 @@ class one2many(_column): def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None): return obj.pool.get(self._obj).name_search(cr, uid, value, self._domain, operator, context=context,limit=limit) + + @classmethod + def _as_display_name(cls, field, cr, uid, obj, value, context=None): + raise NotImplementedError('One2Many columns should not be used as record name (_rec_name)') # # Values: (0, 0, { fields }) create @@ -725,6 +762,10 @@ class many2many(_column): def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None): return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name', operator, value)], offset, limit, context=context) + @classmethod + def _as_display_name(cls, field, cr, uid, obj, value, context=None): + raise NotImplementedError('Many2Many columns should not be used as record name (_rec_name)') + def get_nice_size(value): size = 0 @@ -1078,6 +1119,12 @@ class function(_column): if self._fnct_inv: self._fnct_inv(obj, cr, user, id, name, value, self._fnct_inv_arg, context) + @classmethod + def _as_display_name(cls, field, cr, uid, obj, value, context=None): + # Function fields are supposed to emulate a basic field type, + # so they can delegate to the basic type for record name rendering + return globals()[field._type]._as_display_name(field, cr, uid, obj, value, context=context) + # --------------------------------------------------------- # Related fields # --------------------------------------------------------- @@ -1211,7 +1258,6 @@ class related(function): result[-1]['relation'] = f['relation'] self._relations = result - class sparse(function): def convert_value(self, obj, cr, uid, record, value, read_value, context=None): diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index a1a267bd552..a53c205d8a7 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2280,12 +2280,12 @@ class BaseModel(object): if isinstance(ids, (int, long)): ids = [ids] - rec_name = self._rec_name - if rec_name not in self._columns: - res = [(r['id'], "%s,%s"%(self._name,r['id'])) for r in self.read(cr, user, ids, ['id'], context, load='_classic_write')] - else: - res = [(r['id'], tools.ustr(r[rec_name])) for r in self.read(cr, user, ids, [rec_name], context, load='_classic_write')] - return res + if self._rec_name in self._all_columns: + rec_name_column = self._all_columns[self._rec_name].column + return [(r['id'], rec_name_column.as_display_name(cr, user, self, r[self._rec_name], context=context)) + for r in self.read(cr, user, ids, [self._rec_name], + load='_classic_write', context=context)] + return [(id, "%s,%s" % (self._name, id)) for id in ids] def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100): """Search for records that have a display name matching the given ``name`` pattern if compared