odoo中domain使用详解,波兰表达式

  • A+

odoo有着完善的orm对象处理,domain主要用于数据搜索,封装了sql中查询语句,以及跨数据表的处理。

官方文档请参考:

https://www.sunpop.cn/documentation/12.0/reference/orm.html#domains

 

 

一:domain表达式

domain表达式:通常用来筛选数据记录。它们使用特殊的语法,以便于Odoo ORM 将它们解析后生成对应的SQL WHERE数据库筛选语句。domain通常为一个数组,数组元素为过滤条件,每个条件是一个三元表达式,例如: [(‘state’,’=’,’confirm’), (‘user_id’,’in’,[1,2,3])]
domain多个条件的逻辑运算使用了“波兰表示法”,波兰表示法的特定是操作符置于操作数前,运算顺序为:从左至右读入表达式,遇到一个操作符后跟随两个操作数时,则计算之,然后将结果作为操作数替换这个操作符和两个操作数;重复此步骤,直至所有操作符处理完毕。

 

二:domain的写法

domain表达式是一个条件列表,每个条件是一个形如('field_name', 'operator', value')的元组。

filed_name 是需要筛选的字段,它可以使用点(.)来访问关系模块的字段。
value 是一个Python表达式的值。它可以使用字符值,比如:字符串,数字,布尔值,或则列表、某个字段、用户在context中自定义的有效的值。
operator 可以为:
    常用的操作符:<,>,<=,>=,=,!=。
    '=like'通配符,使用下划线(_)时,匹配一个任意字符,使用百分号(%)时,匹配多个字符。
    'like'匹配一个’%value%’的字符串。’ilike’与此类似但不区分大小写。‘not like’和‘not ilike’也可以使用
    'child of'在层级关系中,筛选子集
    'in'和’not in’筛选是否在一个列表里面,所以,给的值应该是个list。当在’to-many’的关系字段中,‘in’的作用和contains的作用一样

domain表达式是一个包含多项内容的list,因此,可以包含多个条件表达式元组。 默认情况下这些条件之间是用AND逻辑符连接的,也就是说,它只返回满足所有条件的记录集。

也可以用显式的逻辑连接符:and连接符(&,默认使用),或连接符(|)。这些连接符后面跟着两项内容,可以画成递归树的形式理解。

感叹号(!),是非操作符(NOT),作用于紧挨它的后一个项。因此,它应该出现在否定项的前面。比如,['!', ('is_done','=',True)]

 

例子:

['|', ('message_follower_ids', 'in', [user.partner_id.id]),
      '|', ('user_id', '=', user.id), ('user_id', '=', False)]

画成递归树解读:

三:domain的操作符

  • 比较运算符:条件的操作符主要有如下类型
    操作符说明
    =,!=,>,>=,<,<=比较运算,等于,不等于,大于,大于等于,小于,小于等于
    like模糊匹配,可以使用通配符,下划线“_”匹配一个字符,百分号“%”匹配零或者多个字符
    ilike类似like,不区分大小写
    not like模糊不匹配的
    in包含,判断值是否在元素的列表里面
    not in不包含,判断值是否不在元素的列表里面
    child_of判断是否value的子记录,通过_parent_name实现,不太理解
    parent_left用于有 父子关系的模型,整合 parent_path
    parent_right
  • 逻辑运算符,主要用于多个条件处理,逻辑运算符链接。逻辑运算符作为前缀放置于条件前面。:
    "|”(or)
    "&" (and)
    "!"(no)“
    默认逻辑运算符为“&”

在xml中要进行转义,如下表。

>:&gt;

<:&lt;

":&quot;

':&apos;

&:&amp

 

四:算法,domain使用的是波兰表达式

计算的核心思想:

Odoo是使用了波兰表达式,运算波兰表达式时,无需记住运算的层次,只需要直接寻找第一个运算的操作符。以二元运算为例,从左至右读入表达式,遇到一个操作符后跟随两个操作数时,则计算之,然后将结果作为操作数替换这个操作符和两个操作数;重复此步骤,直至所有操作符处理完毕。

简单来说,波兰表示法是一种操作符置于操作数前,并且不需要括号仍然能无歧义地解析表达的方法。具体可参考: https://www.cnblogs.com/cute/p/3977058.html

 

举个栗子

['|','&','|',a,b,c,'&',d,e]

其中a,b,c,e,f,g分别是不带逻辑运算符的表达式,表达式的运算顺序:

['|','&','|',a,b,c,'&',d,e]

['|','&',(a| b),c,'&',d,e]

['|',((a | b) & c),'&',d,e]

['|',((a |b) & c),(d& e)]

[(((a| b) |c)| (d & e))]

逻辑运算符包括

符号说明

丨(or)或,二元运算

&(and)与,二元运算

!(no)非,单目运算

逻辑运算符默认是'与',‘与’运算符可以不写。

实例

“名字为 ABC”,就是一个最简单的单条件Domain。

[('name','=','ABC')]

“名字为 ABC 而且 语言编码不为en_US”,Domain里条件默认逻辑关系就是and,所以如下。

[('name','=','ABC'),

('language.code','!=','en_US')]

“名字为 ABC 而且语言编码不为 en_US 而且国家的编码为 be 或者 de”。

[('name','=','ABC'),

('language.code','!=','en_US'),

'|',('country_id.code','=','be'),

('country_id.code','=','de')]

如果我们要做到这个效果

Aand(B orC)andDandE

先从里面开始,把or提前

Aand(orB C)andDandE

把里面的and提前,去掉括号

andAorB CandD E

所以最后的domain可以这样写

A,'|', B,C,D,E

当然了,我们为什么不写得让自己也容易看一点呢,如下:

A,D,E,'|', B,C

weinxin
我的微信
这是我的微信扫一扫

发表评论

您必须才能发表评论!