在 Odoo14 中最常用的动态过滤或联动domain的方法有两种
1. 使用 上下文 context 和 重写 _search() 或 _name_search() 方法
2. 使用 onchange() 装饰器 的 domain 返回值
示例:
这个图有字段:项目,上级任务,任务
要求:
选择项目后,在选择上级任务时所能选择的上级任务都属于这个项目下的上级任务,
在选择任务的时候所能选择的任务都属与该上级任务下的任务(也属于项目下的任务)
关系:
class ProjTask(models.Model):
_name = 'project.task'
_description = '项目任务'
bill_no = fields.Char(string='单据编号', index=True, copy=False, tracking=True)
project_id = fields.Many2one('project.project', string="项目台账")
name = fields.Char(string='项目名称')
parent_id = fields.Many2one("project.task", string="父项任务")
下面这个是展示到页面的 模型表
class ProjMonthlyReportNextPlanLines(models.Model):
_name = 'proj.monthly.report.next.plan.lines'
_inherit = ['base.bill.line.template']
_description = '下月工作计划'
proj_id = fields.Many2one('project.project', string='项目')
parent_task_id = fields.Many2one('project.task', string='父任务')
task_id = fields.Many2one('project.task', string='任务')
principal_id = fields.Many2one('hr.employee', string='负责人')
使用第一种方法:使用 上下文 context 和 重写 _search() 或 _name_search() 方法
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="proj_monthly_report_next_plan_lines_view_form" model="ir.ui.view">
<field name="name">proj.monthly.report.next.plan.lines.view.form</field>
<field name="model">proj.monthly.report.next.plan.lines</field>
<field name="arch" type="xml">
<form>
<group string="基本信息">
<field name="type" string="类型"/>
<field name="project_id" string="项目名称"
context="{'model':'project.project','type':'type'}"/>
# 这个 context 的值还可以是 字段
</group>
</form>
</field>
</record>
</data>
</odoo>
class ProjectProject(models.Model):
_name = ['project.project']
@api.model
def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None):
args = args or []
domain = []
if 'model' in self.env.context:
if self.env.context['model'] == 'project.project':
domain.append(('id', 'not in', self.env['project.project'].search(
[('state', 'in', ['approval','done'])]).project_id.ids))
# 根据表单其他字段过滤
if self.env.context['type'] == 'M':
domain.append((...))
return super(ProjectProject, self)._search(args + domain, offset, limit, order, count=count,
access_rights_uid=access_rights_uid)
上面是一个联动的列子,你需要过滤那个模型的字段就需要在那个模型下重写_search或 _name_search 方法,当然你的 context 需要写到对应需要过滤的表单下
使用第二种方法: 使用 onchange() 装饰器 的 domain 返回值
这个方法简便且一目了然,了解onchange装饰器的返回值即可:
代码如下:
class ProjMonthlyReportNextPlanLines(models.Model):
_name = 'proj.monthly.report.next.plan.lines'
_inherit = ['base.bill.line.template']
_description = '下月工作计划'
primary_id = fields.Many2one('proj.monthly.report', string='关联主表id')
proj_id = fields.Many2one('project.project', string='项目')
parent_task_id = fields.Many2one('project.task', string='父任务')
task_id = fields.Many2one('project.task', string='任务')
principal_id = fields.Many2one('hr.employee', string='负责人')
@api.onchange('proj_id')
def _onchange_project_id(self):
for record in self:
record.parent_task_id = None
if record.proj_id:
return {
'domain': {
'parent_task_id': [('project_id', '=', record.proj_id.id), ('parent_id', '=', None)]
}
}
@api.onchange('parent_task_id')
def _onchange_parent_task_id(self):
for record in self:
record.task_id = None
if record.parent_task_id:
return {
'domain': {
'task_id': [('project_id', '=', record.proj_id.id), ('parent_id', '=', record.parent_task_id.id)]
}
}