odoo高级应用之 如何修改基类方法

对于熟练开发odoo第三方模块的人员来说,继承重载是很自然很顺滑的操作,我们所写的大部分模块都是在现有模块的基础上的修修补补。那么,现在有一个问题,假如我想修改基类的某个方法,那么该如何做呢?

基类重载不同于三方模块的继承

首先明确,这里的基类的概念,指的是Model\AbstractModel和BaseModel。这些类跟我们平时继承的对象不同的地方在于,基类没有实例化,也就是没有_name属性,不能通过_inherit属性来继承。所以,我们要想修改BaseModel中的一些内置方法,就得另辟蹊径。当然,修改源码是最简便的途径,但是,还是那句话,这样会污染了源码,一旦有了问题,会影响问题的排查速度。

那么究竟应该如何修改基类的内置方法呢?

我们知道python的继承,后定义的方法会覆盖掉前面定义过的方法,我们可以根据这个原理来修改内置类的方法。

举例来说,我们常用的name_search方法定义在BaseModel中,name_search原本接收的参数数量是4个:

1
2
3
4
# models.py>BaseModel
@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
...

现在我们希望给name_search添加一个参数而不改动models.py的源码,那么我们可以新定义一个模块,然后在models.py中这么写:

1
2
3
4
5
6
7
8
9
10
11
12
from odoo import models

...

@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100, options=None):
# override name search in base model.
# add fields in options, to search more fields.
return _name_search(self, name, args, operator, limit=limit, name_get_uid=None, options=options)


models.Model.name_search = name_search

通过对name_search方法的重定义,我们就可以给name_search方法新添加了一个带默认值的参数,带默认值的原因是为了防止因为多加参数而导致的其他模块通过正常方式重写name_search方法而引发异常。

由此,我们可以看出,这种方式的重载的优先级是高于正常的重载的,这也与我们的思维一致。

需要注意的一点是,name_search方法的第一个参数是self,如果name_search方法中的内部方法也被重载了,那么是不能通过self.xxx的方式进行调用的,因为那样调用的是还是原有的方法,对于这种重载,我们需要显式的把self参数传入,就像上面代码中的_name_search方法一样。

你的支持我的动力