最近在odoo project模块的基础上做二开,给task表加了一个版本字段version_id,然后重写了
project表的Task_ids, 并且增加了一个domain,结果折腾了大半天才搞定
这也是最初的写法:
version_id = fields.Many2one("hx.prj.task.plan.version", "计划版本")
task_ids = fields.One2many('project.task', 'project_id', string='Tasks',domain="[('version_id', '=', version_id)]")
结果发现domain不起作用,仔细阅读源代码
def get_domain_list(self, model):
""" Return a list domain from the domain parameter. """
domain = self.domain
if callable(domain):
domain = domain(model)
return domain if isinstance(domain, list) else []
如果domain是字符串就返回空列表,有点懵啊,代码中有很多domain都是用引号括起来的!!!
既然如此,那就把引号去掉吧
不带引号
task_ids = fields.One2many('project.task', 'project_id', string='Tasks',domain=[('version_id', '=', version_id)])
这样写,报错了,
psycopg2.ProgrammingError: can't adapt type 'Many2one'
其实,其他的One2Many字段我也不带引号,是ok的。
实在没有办法了,于是搜索odoo其他的one2many字段,看看domain是怎么写的
发现两个事:
1、one2many的domain确实是不带引号的
2、还有一种写法,用lambda写一个匿名函数
website_message_ids = fields.One2many(domain=lambda self: [('model', '=', self._name), ('message_type', 'in', ['email', 'comment'])])
我尝试了一下这种写法,
task_ids = fields.One2many('project.task', 'project_id', string='Tasks',domain=lambda self:[('version_id', '!=', False),('version_id', '=', self.version_id.id)])
这种写法可以引用self, 很意外,测试通过了。
仔细看上面的get_domain_list 函数,domain 可以是一个函数
if callable(domain):
domain = domain(model)
关于domain, 要学习的地方还有很多,特别是关系字段的domain,更复杂一些。