Olivier Dony (OpenERP) has proposed merging 
lp:~openerp-dev/openobject-server/trunk-name-get-fixes-odo into 
lp:openobject-server.

Requested reviews:
  Xavier (Open ERP) (xmo)

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-name-get-fixes-odo/+merge/118061

Introduces an improved name_get implementation, supporting a few more fields 
type used as _rec_name (such as many2one).
The actual rendering of the "display name" is delegated to the column class, 
and computed based on the value returned by read() for the column.

Funky @classmethod stuff was necessary to allow column types to delegate to 
other types, such as 'function' types which can delegate to the real type they 
emulate.

The 'display_name' term was used because it is being discussed for the new API 
to add a virtual 'display_name' column to all models, allowing clients to read 
the 'name_get' value along with regular columns. It looks appropriate too.

Also fixes a few shortcomings of the latest patches to name_get, such as 
supporting inherited columns and avoiding a useless read() call with only the 
'id' column.
-- 
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-name-get-fixes-odo/+merge/118061
Your team OpenERP R&D Team is subscribed to branch 
lp:~openerp-dev/openobject-server/trunk-name-get-fixes-odo.
=== modified file 'openerp/osv/fields.py'
--- openerp/osv/fields.py	2012-07-23 14:05:02 +0000
+++ openerp/osv/fields.py	2012-08-03 10:44:21 +0000
@@ -127,6 +127,23 @@
         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 @@
                     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 @@
     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 @@
     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 @@
     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 @@
         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 @@
                 result[-1]['relation'] = f['relation']
         self._relations = result
 
-
 class sparse(function):   
 
     def convert_value(self, obj, cr, uid, record, value, read_value, context=None):        

=== modified file 'openerp/osv/orm.py'
--- openerp/osv/orm.py	2012-08-01 08:01:55 +0000
+++ openerp/osv/orm.py	2012-08-03 10:44:21 +0000
@@ -2280,12 +2280,12 @@
         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

_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help   : https://help.launchpad.net/ListHelp

Reply via email to