Odoo(OpenERP) Domains and Polish Notations (Part 3)
It’s
good to know that OpenERP uses Polish Notation for Domain filters. And in the
previous parts we explained what is notations and how to be used and the
conversion process between each other and for more information about the polish
notation just click these links:
Domains
A
domain is a list of criterion, each criterion being a triple (either a list or
a tuple) of (field_name, operator, value) where:
field_name (str)
a field name of the current model,
or a relationship traversal through a Many2one using dot-notation e.g. 'street' or 'partner_id.country'
operator (str)
- A comparison operator between the
criterion’s field and value.
- Valid operators are =, !=,
>, >=, <, <=, like, ilike, in, not in,
child_of, parent_left, parent_right (for details go to this file: openerp/osv/expression.py)
child_of, parent_left, parent_right (for details go to this file: openerp/osv/expression.py)
value
- Variable type, must be comparable
(through operator) to the named field
- Valid value to compare with the values of field_name, depending on its
type
Domain
criteria can be combined using logical operators in prefix form:
'&':
logical AND, default operation to combine criteria following one
another.
'|':
logical OR
'!':
logical NOT
Tip: Mostly to negate combinations of criteria, Individual criterion generally have a negative form (e.g. = -> !=, < -> >=) which is simpler than negating the positive.
Example
To
search for partners named ABC, from belgium or germany, whose
language is not english:
[('name','=','ABC'),
('language.code','!=','en_US'),
'|',('country_id.code','=','be'),
('country_id.code','=','de')]
This
domain is interpreted as:
(name is 'ABC')
AND (language is NOT english)
AND (country is Belgium OR Germany)
How to write different domain filters:
1-
Simple condition in programming:
a- if field1 = 10
will be written in odoo like that:
domain = [(‘field1′,’=’,10)] # where field1 should be a field
in the model and 10 will be the value.
OR domain = [(‘field1′,’=’,field2)] #
where field1 and field2 should
be the fields in the model.
b- Condition AND
if field1 = 5 and field2 = 10
In OpenERP domain filter, it will be
written as:
domain = [(‘field1′,’=’,5),(‘field2′,’=’,10)]
OR domain
= [(‘field1′,’=’,field3),(‘field1′,’=’,field3)]
Note that if you don’t specify any condition at the
beginning and condition will be
applied.
c- Condition OR
if field1 = 5 or field2 = 10
In OpenERP domain filter, it will be
written as:
ie, domain
= [‘|’, (‘field1′,’=’,5),(‘field2′,’=’,10)]
or domain
= [‘|’, (‘field1′,’=’,field3),(‘field1′,’=’,field3)]
2-
Complex Condition
2.1- Simple condition:
if field1 = 5 or (field2 ! = 10 and field3 = 12)
In OpenERP domain filter, it will be
written as:
domain =
[‘|’,(‘field1′,’=’,5),(‘&’,(‘field2′,’!=’,10),(‘field3′,’=’,’12’))]
2.2- Complex Condition:
As
we known OpenERP uses Polish Notation for Domain filters.
If we have a condition like that: ( A OR B) AND ( C OR D OR E)
should converted to the polish notation as AND OR A B OR OR C D E As follow:
We should start from the most right character i.e the ‘)’ character.
If we have a condition like that: ( A OR B) AND ( C OR D OR E)
should converted to the polish notation as AND OR A B OR OR C D E As follow:
We should start from the most right character i.e the ‘)’ character.
Input
|
Prefix_Stack
|
Stack
|
)
|
Empty
|
)
|
E
|
E
|
)
|
OR
|
E
|
) OR
|
D
|
ED
|
) OR
|
OR
|
ED
|
) OR OR
|
C
|
EDC
|
) OR OR
|
(
|
EDC OR OR
|
Empty
|
AND
|
EDC OR OR
|
AND
|
)
|
EDC OR OR
|
AND )
|
B
|
EDC OR OR B
|
AND )
|
OR
|
EDC OR OR B
|
AND ) OR
|
A
|
EDC OR OR B A
|
AND ) OR
|
(
|
EDC OR OR B A
OR
|
AND
|
Empty
|
EDC OR OR B A
OR AND
|
Empty
|
Now by reversing the final result in the prefix_stack we will get
AND
OR A B OR OR CDE ## As we expected
You can also use ‘in’ operator instead of writing three separate tuples with OR operator like
['&',('field2',
'in', ['A', 'B']),('state', 'in', ['open', 'closed', 'draft'])]
And
for checking the various use of the domain filters in the actions list from
Settings
> Actions > Window Actions (technical features should be on)
The simplest way:
(1) Start with the outermost operator
and move it to the start of the expression.
“(A operator B)” becomes
“operator (A B)”
(2) Repeat step 1 for each sub
expression with an operator to move.
“A (B operator C)” becomes
“operator A (B operator C)” then “operator A (operator B C)”
(3)
Remove all brackets
“A operator (B operator C)”
becomes “operator A operator B C”
SO for our example: (A OR B) AND (C OR D
OR E) we will convert it like that:
-
According to step (1) the expression will be:
AND (A OR B) (C OR D OR E)
-
According to step (2) the expression will be:
Left Side: AND (OR A B) (C OR D OR E)
Right Outer Side: AND (OR A B) (OR C (D OR E))
Right Inner Side: AND (OR A B) (OR C (OR D E))
-
According to step (3) the expression will be (remove brackets):
AND or A B or C or D E
-
According to opener domain syntax this result would be written
as:
[ ‘&’,’|’, (A),(B),’|’, (C),
‘|’, (D), (E) ]
Note: OpenERP uses the
polish(prefix) notation, And we can also use the reverse(postfix) polish
notation for writing domain filters.
For more information: Click here
And just as an example:
The infix expression "(3 +
5) * (7 - 2)" can be written down like this in RPN: 3 5 + 7 2 - *
Note: The reversed notation is
exactly the same, but enables you to resolve without going back and forth.