We have stumbled upon context and domain several times. We have seen that window actions are able to set them and relational fields in models can also have them as attributes.
The context is a dictionary carrying session data that can be used on both the client-side user interface and the server-side ORM and business logic.
On the client side it can carry information from one view to next, such as the ID of the record active on the previous view, after following a link or a button, or to provide default values to be used in the next view.
On the server side, some recordset field values can depend on the locale settings provided by the context. In particular the lang
key affects the value of translatable fields. Context can also provide signals for server-side code. For example, the active_test
key when set to False
changes the behavior of ORM's search()
method so that it does not filter out inactive records.
An initial context from the web client looks like this:
{'lang': 'en_US', 'tz': 'Europe/Brussels', 'uid': 1}
You can see the lang
key with the user language, tz
with the time zone information, and uid
with the current user ID.
When opening a form from a link or a button in a previous view, an active_id
key is added to the context, with the ID of record we were positioned at, in the origin form. In the particular case of list views, we have an active_ids
context key containing a list of the record IDs selected in the previous list.
On the client side, the context can be used to set default values or activate default filters on the target view, using keys with the default_
or default_search_
prefixes. Here are some examples:
To set the current user as a default value of the user_id
field, we will use the following:
{'default_user_id': uid}
To have a filter_my_tasks
filter activated by default on the target view, we will use this:
{'default_search_filter_my_tasks': 1}
The domain is used to filter data records. They use a specific syntax that the Odoo ORM parses to produce the SQL WHERE expressions that will query the database.
A domain expression is a list of conditions. Each condition is a ('field_name', 'operator', value')
tuple. For example, this is a valid domain expression, with only one condition: [('is_done','=',False)]
.
Following is an explanation of each of these elements:
The field name is the field being filtered, and can use dot-notation for fields in related models.
The value is evaluated as a Python expression. It can use literal values, such as numbers, Booleans, strings, or lists, and can use fields and identifiers available in the evaluation context. There are actually two possible evaluation contexts for domains:
The operator can be:
<
, >
, <=
, >=
, =
, !=
.'=like'
matches against a pattern, where the underscore symbol, _
, matches any single character, and the percentage symbol, %
, matches any sequence of characters.'like'
matches against a '%value%'
pattern. The 'ilike'
is similar but case insensitive. The 'not like'
and 'not ilike'
operators are also available.'child of'
finds the children values in a hierarchical relation, for the models configured to support them.'in'
and 'not in'
are used to check for inclusion in a given list, so the value should be a list of values. When used on a "to-many" relation field the in
operator behaves like a contains
operator. A domain expression is a list of items, and can contain several condition tuples. By default these condition will implicitly be combined using the AND logical operator. This means that it will only return records meeting all these conditions.
Explicit logic operators can also be used: the ampersand symbol, '&'
, for AND operations (the default), and the pipe symbol,'|'
, for OR operations. These will operate on the next two items, working in a recursive way. We'll look at this in more detail in a moment.
The exclamation point, '!'
, represents the NOT operator, is also available and operates on the next item. So, it should be placed before the item to be negated. For example, the ['!', ('is_done','=',True)]
expression would filter all not done records.
The "next item" can also be an operator item acting on its next items, defining nested conditions. An example may help us to better understand this.
In server-side record rules, we can find domain expressions similar to this one:
['|', ('message_follower_ids', 'in', [user.partner_id.id]), '|', ('user_id', '=', user.id), ('user_id', '=', False) ]
This domain filters all the records where the current user is in the follower list, is the responsible user, or does not have a responsible user set.
The first '|'
(OR) operator acts on the follower's condition plus the result of the next condition. The next condition is again the union of two other conditions: records where either the user ID is the current session user or it is not set.
The following diagram illustrates this nested operators resolution: