openerp中get_name()的不同表现 openerp中每个类都有一个get_name()方法,或者在类内用代码实现这个方法, 或者默认继承父类中的这个方法。 它的签名为 def name_get(self, cr, uid, ids, context=None)
其中ids为要查询记录的id号, 其数据类型为list。 【1】 继承父类get_name时的, 具有很好的容错性 其ids中的记录号可以是不存在的号码, 如果只有一个号码, ids的类型可以不使用列表,而直接使用整数 例如 res.user 没有实现自己的name_get, 而是继承了父类的name_get, 如下是其测试代码 import xmlrpclib sock=xmlrpclib.ServerProxy("http://127.0.0.1:8069/xmlrpc/object" print sock.execute("demo", 1,"admin", "res.users","name_get", [1] ) print sock.execute("demo", 1,"admin", "res.users","name_get", 1) print sock.execute("demo", 1,"admin", "res.users","name_get", [1, 0, -1] )
上例中,使用了三种不同的ids来调用name_get的方法,其结果都是一样的, 为[[1, 'Administrator']], 因为记录号 0和-1 不存在, 因此不返回他们的查询结果, 也不抛出异常。 【2】模块内部完美地实现了get_name方法, 像父类方法一样,具有很好的兼容性,比如 product_category def name_get(self, cr, uid, ids,context=None): if isinstance(ids, (list, tuple)) andnot len(ids): return[] if isinstance(ids, (long, int)): ids = [ids] reads = self.read(cr, uid, ids,['name','parent_id'], context=context) res = [] for record in reads: name = record['name'] if record['parent_id']: name = record['parent_id'][1]+'/ '+name res.append((record['id'], name)) return res
这段代码使用instance判断ids的类型,如果是整数或浮点数, 则转换为列表。对于ids中不存在的记录号,self.read具有兼容性,因此, 本模块的name_get就具备了响应的兼容性。
【3】模块内实现get_name方法时, ids是整数而不是列表, 会抛出异常。 例如类account.tax: def name_get(self, cr, uid, ids,context=None): if not ids: return [] res = [] for record in self.read(cr, uid, ids,['description','name'], context=context)
name = record['description']and record['description] or record['name'] res.append((record['id'], name)) return res
这段代码没有判断ids的数据类型,当ids的数据类型不是列表, 它没有进行适当的转换。因此会导致错误发生 【4】模块内实现get_name方法时, ids中出现不存在的记录号时, 会抛出异常, 例如类 event.event def name_get(self, cr, uid, ids,context=None): if not ids: return[] if isinstance(ids, (long, int)): ids = [ids] res = [] for record in self.browse(cr, uid, ids,context=context): date =record.date_begin.split(" ")[0] date_end =record.date_end.split(" ")[0] if date != date_end: date += ' - ' + date_end display_name = record.name + ' (' + date +')' res.append((record['id'],display_name)) return res
这段代码内调用了自己的browse方法, 如果ids中的id号不存在,browse_record会抛出异常, 因此会导致其name_get方法也抛出异常
【5】最后,我们看一个奇葩,类product_pricelist中的name_get def name_get(self, cr, uid, ids,context=None): result= [] if notall(ids): returnresult for pl inself.browse(cr, uid, ids, context=context): name =pl.name + ' ('+ pl.currency_id.name + ')' result.append((pl.id,name)) returnres
---- 它没有对ids的类型进行判断, 因此当ids为整数时,会抛出异常 ---- 它调用的函数是self.browse,而不是self.read, 因此,如果ids中出现了不存在的记录号,也会抛出异常 ---- 更糟糕的是,如果ids中出现了数字零, 那么all(ids)就为假, 这个函数会直接返回一个空的列表。虽然没有抛出异常,但是它并不按我们期望的那样工作。 这个样子最惹人恨了。
erp中文社区的许多朋友在摇摇欲试,要自己在平板电脑上开发oe模块。 这就免不了要用xml-rpc调用openerp的各种模块。 因此需要关注其行为的差异, 以免掉到坑里。
|