8.扩展现有模块-继承机制
即使是对于现有的模块,推荐的做法也是通过新建一个模块来达到扩展和修改现有模块的目的。具体方法就是在python中的类里面使用 _inherit
属性。这标识了将要扩展的模块。新的模型继承了父模型的所有特性,我们只需要声明一些我们想要的修改就行了。通过这种继承机制的修改可从模型到视图到业务逻辑等对原模块进行全方位的修改。
实际上,Odoo模型在我们定义的模型之外,它们都在注册中心注册了的,所谓全局环境的一部分,可以用 self.env[model name]
来引用之。比如要引用 res.partner
模型,我们就可以写作self.env['res.partner']
。
8.1 给模块增加field
如下代码就是首先通过 _inherit
继承原模块,然后再增加一些field:
from openerp import models, fields, apiclass TodoTask(models.Model):_inherit = 'todo.task'user_id = fields.Many2one('res.users',string='Responsible')date_deadline = fields.Date('Deadline')
关于 res.users
和 res.partner
具体是雇员还是合作伙伴什么的,这个以后再摸清楚,这里先简单将其看作一个SQL表格,然后Many2one前面讲过了就是根据某个给定的SQL表格来生成一个下拉选单,具体是引用的该SQL表格的那个表头属性,这里应该还有一个细节讨论。
不管怎么说,现在我们通过新建一个模块 todo_user ,如前面描述的将模块设置配置好之后,原模块 todo_app 的todo.task模型就增加了新的两个field了,也就是两个新的表头了。
8.2 修改已有的field
按照上面的继承机制,我们可以如上类似处理,只修改你希望更改的某个field的某个属性即可。如下:
name = fields.Char(help="can I help you")
这样原模型的namefield额外增加了help帮助信息了。
Figure 26: help帮助信息
8.3 重载原模型的方法
读者一定已经想到了,类似的在这种继承机制下,可以通过重写原模型的方法来重载该方法。事实上确实可以这样做,而这里要讲的是还有一种更加优雅的继承原模型的方法,那就是通过 super()
来调用父类的方法3。
首先我们看到下面这个例子:
@api.multi def do_clear_done(self): domain = [('is_done', '=', True), '|', ('user_id', '=', 'self.env.uid'), ('user_id','=',False)] done_recs = self.search(domain) done_recs.write({'active':False}) return True
这里涉及到Odoo新API的一些东西,这里先浅尝辄止讲一下。
8.3.1 什么是Recordset
Odoo8引入了一种新的ORM API,老的API也兼容,但推荐使用新的API,因为新的API更加简洁和方便。
首先是模型(model),其对应的就是python的类,具体类的实例就是对应现实世界的某个对象。然后老式的简单ORM封装就是将这些类的具体某些数据对应到SQL的数据库的一条记录(record)中去。新的API引入一个核心的概念就是 Recordset ,Recordset是个什么东西呢?就是前面讲的某一个模型(类)的所有对象(具体的实例)的集合就是一个Recordset对象。——这是recordset最大的情况,一个重要的限定条件就是其内元素必定是相同模型的,由这个最大的集合情况然后删除过滤掉一些元素(记录)之后仍然是recordset对象。
按照官方文档的描述是,一个Recordset对象应该是已经排序了的同一模型的对象的集合。他还指出虽然现在还可以存放重复的元素,这个以后可能会变的。同时你从名字可能猜到这个Recordset对象应该支持集合的一些操作,事实确实如此。
比如Recordset支持如下运算:
record in recset1 # include record not in recset1 # not include recset1 + recset2 # extend recset1 | recset2 # union recset1 & recset2 # intersect recset1 - recset2 # difference recset.copy() # copy the recordset (not a deep copy)
上面的操作只有 +
还保留了次序,不过recordset是可以排序的,关于次序比如使用:
for record in recordset: print(record)
具体的次序是否像集合set一样是不一定的还是如何呢?这里需要进一步的讨论。
8.3.2 Odoo里面的domain语法
本小节主要参考了 这个网页 。
Odoo里面的domain语法使用比较广泛,其就好像一个过滤器,应该对应的是SQL的SELECT语句。最基本的语句形式是