ODOO 域(条件)表达式 DOMAIN、FORCE_DOMAIN及FILTER_DOMAIN 的应用场景及应用方式详解
在odoo中,域(条件)过滤是一个非常重要的部分,不仅可以为用户提供强大的数据检索功能,还能使得程序在开发者设计下,更有层次感、界限感。
首先,域是用于选择模型记录子集的条件列表。 每个条件都是一个三元组,其中包含一个字段名称,一个运算符和一个值。本文将说明domain、force_domain及filter_domain的特点区别及用法。
一. domain
domain 是众多odoo萌新开发者最先接触到的条件过滤属性。
- 客户端接口中选择记录时,可以将“domain”参数添加到关系字段中,以限制关系的有效记录*(这里的关系字段比较重要)*。
例如,你在模型B中,定义了一个字段,关联的模型A,但你想在模型B的视图中,只可以选择模型A中类型是2的记录,你可以这样做,在py文件中,为other_id字段上增加domain属性:
class ModelA(models.Model):
_name = 'model.a'
name = fields.Char('Name')
type = fields.Selection([
('1', 'Type One'),
('2', 'Type Two')
], string="Type")
class ModelB(models.Model):
_name = 'model.B'
name = fields.Char('Name')
other_id = fields.Many2one('model.a',string='Relational Fields',domain=[('type', '=', '2')])
除了上面的方式,你也可以在xml文件中,为other_id设置domain :
<form>
<sheet>
<group>
<field name="name"/>
<field name="other_id" domain="[('type', '=', '2')]"/>
</group>
</sheet>
</form>
- 想要实现在打开某个菜单时,只显示符合条件的记录,可以将“domain”添加到动作中,以过滤出符合条件的记录。
例如,我们要为模型A创建两个菜单,一个菜单点进去后只看类型为1的记录,另一个菜单点进去只看类型为2的记录。
<record id="action_model_a_filter_1" model="ir.actions.act_window">
<field name="name">测试动作1</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">model.a</field>
<field name="domain">[('type', '=', '1')]</field>
</record>
<record id="action_model_a_filter_2" model="ir.actions.act_window">
<field name="name">测试动作2</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">model.a</field>
<field name="domain">[('type', '=', '2')]</field>
</record>
<menuitem id="menu_filter_1" name="只看类型为1的" action="action_model_a_filter_1" sequence="1"/>
<menuitem id="menu_filter_2" name="只看类型为2的" action="action_model_a_filter_2" sequence="2"/>
二 domain_force
domain_force 也是条件过滤的一种方式,它被使用在权限规则中。
在试图设置群组,并为群组指定不同规则时,可以将“domain_force”添加到规则中,以过滤出符合条件的记录。
例如:为模型A设置两个角色:普通角色和管理员角色。管理员角色可以看所有人创建的记录,普通角色只可以看自己创建的记录。你可以这样做:
<!-- 创建群组分类 -->
<record model="ir.module.category" id="module_category_model_a">
<field name="name">测试分类权限</field>
<field name="description">描述</field>
<field name="sequence">20</field>
</record>
<!-- 创建角色分组 -->
<record id="group_model_a_user" model="res.groups">
<field name="name">普通角色</field>
<field name="category_id" ref="module_category_model_a"/>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="group_model_a_admin" model="res.groups">
<field name="name">管理员角色</field>
<field name="category_id" ref="module_category_model_a"/>
<field name="implied_ids" eval="[(4, ref('group_model_a_user'))]"/>
</record>
<!-- 指定角色规则 -->
<record id="ir_rule_model_a_user" model="ir.rule">
<field name="name">自己创建的</field>
<field name="model_id" ref="当前模块名.model_model_a"/>
<field name="domain_force">[('create_uid','=',user.id)]</field>
<field name="groups" eval="[(4, ref('当前模块名.group_model_a_user'))]"/>
</record>
<record id="ir_rule_model_a_admin" model="ir.rule">
<field name="name">所有的</field>
<field name="model_id" ref="当前模块名.model_model_a"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('当前模块名.group_model_a_admin'))]"/>
</record>
三 filter_domain
filter_domain 被应用在搜索视图中的fileld标签上,它们用作预定义搜索的切换。在使用filter_domain时,可以使用 self 变量,将用户输入的值注入自定义域。可以用来生成比“操作符”更灵活的域。
- 想要实现为搜索视图增加检索项,以能够使客户快速检索某字段时,使用将“filter_domain”,以检索出符合条件的记录。
例如:假设我们有一个员工模型,我们需要为搜索视图增加一个模糊检索,这个检索是要求将符合用户输入的值的记录过滤出来,我们可以这么做:
<search string="Empoyees">
<field name="name" filter_domain="[('name','ilike',self)]" string="Name"/>
</search>
这里的self 就是用户输入的值。
- 除了上面的用法之外,filter_domain 还有个更强大的用法,就是过滤某关系字段符合条件的记录。
比如,在下面的模型中,我们为员工指定一个部门:
class Department(models.Model):
_name = 'zerone.department'
name = fields.Char('Department Name')
employee_ids = fields.One2many('zerone.employee','department_id',string="Employee_ids")
class Employee(models.Model):
_name = 'zerone.employee'
name = fields.Char('Employee Name')
department_id= fields.Many2one('zerone.department',string='Belong Depart')
我们想为部门模型的搜索视图增加一个检索项,要求在检索时,输入一个部门名,能检索出符合条件的部门,输入一个员工姓名,也能检索出该员工所在的部门,我们可以这么做:
<search string="Departments">
<field name="name" filter_domain="['|',('name','ilike',self),('employee_ids.name','ilike',self)]" string="Department name OR Employee name"/>
</search>
此外:在使用变量self时,可以对其进行拼接,就像下面这样(摘抄自源码):
<record id="view_account_group_search" model="ir.ui.view">
<field name="name">account.group.search</field>
<field name="model">account.group</field>
<field name="arch" type="xml">
<search string="Account groups">
<field name="name" filter_domain="['|', ('code_prefix', '=like', str(self) + '%'), ('name', 'ilike', self)]" string="Account group"/>
</search>
</field>
</record>
原文来自:ODOO 域(条件)表达式 DOMAIN、FORCE_DOMAIN及FILTER_DOMAIN 的应用场景及应用方式