如果遇到有些场景中,多个模型有很多相同字段或者相同功能,可以通过postsql的表继承特性,将多个模型抽象出一个父模型,将相同功能和相同字段放到父模型当中,独特的有差异的字段或者属性放到子模型中,这样子表的记录和父表的记录可以保持一致,增删改查保持同步
缺点:需要修改框架底层代码
**
实现方式可以参照ir.actions.actions模型及其子模型的实现方式,在odoo框架自带模块中的odoo/odoo/addons/base模块中
**
具体实现方式如下:
需要定义一个sql文件,先创建出子父级表的表名和继承关系,我这里放在模块的data目录下面,命名为base_data.sql
CREATE TABLE if not exists 父模型表名称 (
id serial,
primary key(id)
);
CREATE TABLE if not exists 子模块1表名 (primary key(id)) INHERITS (父模型表名称);
CREATE TABLE if not exists 子模块2表名 (primary key(id)) INHERITS (父模型表名);
CREATE TABLE if not exists 子模块3表名 (primary key(id)) INHERITS (父模型表名);
父表和子表需要一个相同字段,用于保存父表记录时区分是哪个子表的记录.
import odoo.modules
import logging
_logger = logging.getLogger(__name__)
class 父表模型类名(models.Model):
_name = '父表模型名'
_table = '当前模型在数据库中存的表的名称'
type = fields.Char(string='子表记录') #用于区分是哪个子表的记录
# ......字段定义
def init(self):
'''
执行data目录下的sql文件,建立数据库中物资相关表的表继承关系
'''
f = odoo.modules.get_module_resource('sql文件所在模块名称', 'sql文件所在目录(如data)', 'base_data.sql')
if not f:
m = "File not found: 'base.sql' (provided by module 'base')."
_logger.critical(m)
raise IOError(m)
with odoo.tools.misc.file_open(f) as base_sql_file:
self._cr.execute(base_sql_file.read())
子表:子模型示例如下
class 子表模型名(models.Model):
_name = '子模型名称'
_table = '子模型数据库保存的表名称' # 需要和sql文件中定义的保持一致
type = fields.Char(default='子表模型名称(_name属性定义的名称)') # 用于父表中区分记录是哪个子表的,用_name容易区分,也可以保存其他的字符串区分
# ......其他字段定义
最后一步:修改fields.py中更新外键函数
文件路径为:odoo/odoo/fields.py
def update_db_foreign_key(self, model, column):
comodel = model.env[self.comodel_name]
# foreign keys do not work on views, and users can define custom models on sql views.
if not model._is_an_ordinary_table() or not comodel._is_an_ordinary_table():
return
# ir_actions is inherited, so foreign key doesn't work on it
**
此处需要新增or关系判断字段是不是关联父模型,和ir.actions.actions一样,跳过创建外键的逻辑
**
if not comodel._auto or comodel._table == 'ir_actions' or comodel._table == '父模型表名称':
return
# create/update the foreign key, and reflect it in 'ir.model.constraint'
process = sql.fix_foreign_key if column else sql.add_foreign_key
new = process(model._cr, model._table, self.name, comodel._table, 'id', self.ondelete or 'set null')
if new:
conname = '%s_%s_fkey' % (model._table, self.name)
model.env['ir.model.constraint']._reflect_constraint(model, conname, 'f', None, self._module)
这样就可以实现父模型和子模型记录保持同步