[IMP] core: odoo.domain
odoo/odoo#170009 closes odoo/documentation#10214 Related: odoo/enterprise#65013 Related: odoo/upgrade-util#99 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
parent
a88d46164b
commit
87b489d36e
@ -257,7 +257,8 @@ it uses the values of other *fields*, it should specify those fields using
|
||||
|
||||
* computed fields are not stored by default, they are computed and
|
||||
returned when requested. Setting ``store=True`` will store them in the
|
||||
database and automatically enable searching.
|
||||
database and automatically enable searching and grouping.
|
||||
Note that by default, ``compute_sudo=True`` is set on the field.
|
||||
* searching on a computed field can also be enabled by setting the ``search``
|
||||
parameter. The value is a method name returning a
|
||||
:ref:`reference/orm/domains`. ::
|
||||
@ -267,7 +268,7 @@ it uses the values of other *fields*, it should specify those fields using
|
||||
def _search_upper(self, operator, value):
|
||||
if operator == 'like':
|
||||
operator = 'ilike'
|
||||
return [('name', operator, value)]
|
||||
return Domain('name', operator, value)
|
||||
|
||||
The search method is invoked when processing domains before doing an
|
||||
actual search on the model. It must return a domain equivalent to the
|
||||
@ -275,8 +276,9 @@ it uses the values of other *fields*, it should specify those fields using
|
||||
|
||||
.. TODO and/or by setting the store to True for search domains ?
|
||||
|
||||
* Computed fields are readonly by default. To allow *setting* values on a computed field, use the ``inverse``
|
||||
parameter. It is the name of a function reversing the computation and
|
||||
* computed fields are readonly by default. To allow *setting* values on a
|
||||
computed field, use the ``inverse`` parameter.
|
||||
It is the name of a function reversing the computation and
|
||||
setting the relevant fields::
|
||||
|
||||
document = fields.Char(compute='_get_document', inverse='_set_document')
|
||||
@ -854,7 +856,7 @@ Common ORM methods
|
||||
|
||||
.. currentmodule:: odoo.models
|
||||
|
||||
Create/update
|
||||
Create/Update
|
||||
-------------
|
||||
|
||||
.. todo:: api.model_create_multi information
|
||||
@ -900,10 +902,11 @@ Fields
|
||||
Search domains
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
A domain is a list of criteria, each criterion being a triple (either a
|
||||
``list`` or a ``tuple``) of ``(field_name, operator, value)`` where:
|
||||
A :class:`~odoo.fields.Domain` is a first-order logical expression used for
|
||||
filtering and searching recordsets.
|
||||
A domain can be a simple condition ``(field_expr, operator, value)`` where:
|
||||
|
||||
* ``field_name`` (``str``)
|
||||
* ``field_expr`` (``str``)
|
||||
a field name of the current model, or a relationship traversal through
|
||||
a :class:`~odoo.fields.Many2one` using dot-notation e.g. ``'street'``
|
||||
or ``'partner_id.country'``. If the field is a date(time) field, you can also
|
||||
@ -914,7 +917,7 @@ A domain is a list of criteria, each criterion being a triple (either a
|
||||
They all use an integer as value.
|
||||
|
||||
* ``operator`` (``str``)
|
||||
an operator used to compare the ``field_name`` with the ``value``. Valid
|
||||
an operator used to compare the ``field_expr`` with the ``value``. Valid
|
||||
operators are:
|
||||
|
||||
``=``
|
||||
@ -933,11 +936,11 @@ A domain is a list of criteria, each criterion being a triple (either a
|
||||
unset or equals to (returns true if ``value`` is either ``None`` or
|
||||
``False``, otherwise behaves like ``=``)
|
||||
``=like``
|
||||
matches ``field_name`` against the ``value`` pattern. An underscore
|
||||
matches ``field_expr`` against the ``value`` pattern. An underscore
|
||||
``_`` in the pattern stands for (matches) any single character; a
|
||||
percent sign ``%`` matches any string of zero or more characters.
|
||||
``like``
|
||||
matches ``field_name`` against the ``%value%`` pattern. Similar to
|
||||
matches ``field_expr`` against the ``%value%`` pattern. Similar to
|
||||
``=like`` but wraps ``value`` with '%' before matching
|
||||
``not like``
|
||||
doesn't match against the ``%value%`` pattern
|
||||
@ -949,7 +952,7 @@ A domain is a list of criteria, each criterion being a triple (either a
|
||||
case insensitive ``=like``
|
||||
``in``
|
||||
is equal to any of the items from ``value``, ``value`` should be a
|
||||
list of items
|
||||
collection of items
|
||||
``not in``
|
||||
is unequal to all of the items from ``value``
|
||||
``child_of``
|
||||
@ -968,12 +971,13 @@ A domain is a list of criteria, each criterion being a triple (either a
|
||||
:attr:`~odoo.models.Model._parent_name`).
|
||||
``any``
|
||||
matches if any record in the relationship traversal through
|
||||
``field_name`` (:class:`~odoo.fields.Many2one`,
|
||||
``field_expr`` (:class:`~odoo.fields.Many2one`,
|
||||
:class:`~odoo.fields.One2many`, or :class:`~odoo.fields.Many2many`)
|
||||
satisfies the provided domain ``value``.
|
||||
The ``field_expr`` should be a field name.
|
||||
``not any``
|
||||
matches if no record in the relationship traversal through
|
||||
``field_name`` (:class:`~odoo.fields.Many2one`,
|
||||
``field_expr`` (:class:`~odoo.fields.Many2one`,
|
||||
:class:`~odoo.fields.One2many`, or :class:`~odoo.fields.Many2many`)
|
||||
satisfies the provided domain ``value``.
|
||||
|
||||
@ -981,19 +985,42 @@ A domain is a list of criteria, each criterion being a triple (either a
|
||||
variable type, must be comparable (through ``operator``) to the named
|
||||
field.
|
||||
|
||||
Domain criteria can be combined using logical operators in *prefix* form:
|
||||
:class:`~odoo.fields.Domain` can be used as a builder for domains.
|
||||
|
||||
``'&'``
|
||||
logical *AND*, default operation to combine criteria following one
|
||||
another. Arity 2 (uses the next 2 criteria or combinations).
|
||||
``'|'``
|
||||
logical *OR*, arity 2.
|
||||
``'!'``
|
||||
logical *NOT*, arity 1.
|
||||
.. code-block:: python
|
||||
|
||||
.. note:: Mostly to negate combinations of criteria
|
||||
Individual criterion generally have a negative form (e.g. ``=`` ->
|
||||
``!=``, ``<`` -> ``>=``) which is simpler than negating the positive.
|
||||
# parse a domain (from list to Domain)
|
||||
domain = Domain([('name', '=', 'abc'), ('phone', 'like', '7620')])
|
||||
|
||||
# serialize domain as a list (from Domain to list)
|
||||
domain_list = list(domain)
|
||||
|
||||
# simple domains
|
||||
d1 = Domain('name', '=', 'abc')
|
||||
d2 = Domain('phone', 'like', '7620')
|
||||
|
||||
# combine domains
|
||||
d3 = d1 & d2 # and
|
||||
d4 = d1 | d2 # or
|
||||
d5 = ~d1 # not
|
||||
|
||||
# combine and parse multiple domains (any iterable of domains)
|
||||
Domain.AND([d1, d2, d3, ...])
|
||||
Domain.OR([d4, d5, ...])
|
||||
|
||||
# constants
|
||||
Domain.TRUE # true domain
|
||||
Domain.FALSE # false domain
|
||||
|
||||
.. automethod:: odoo.fields.Domain.iter_conditions
|
||||
|
||||
.. automethod:: odoo.fields.Domain.map_conditions
|
||||
|
||||
A domain is serialized as a ``list`` of criteria, each criterion being a triple
|
||||
(either a ``list`` or a ``tuple``) representing a simple condition.
|
||||
Domain criteria can be combined using logical operators in a *prefix* notation.
|
||||
You can combine 2 domains using ``'&'`` (AND), ``'|'`` (OR)
|
||||
and you can negate 1 using ``'!'`` (NOT).
|
||||
|
||||
.. example::
|
||||
|
||||
@ -1013,6 +1040,7 @@ Domain criteria can be combined using logical operators in *prefix* form:
|
||||
|
||||
[('birthday.month_number', '=', 2)]
|
||||
|
||||
|
||||
Unlink
|
||||
------
|
||||
|
||||
|
@ -7,6 +7,8 @@ Changelog
|
||||
Odoo Online version 18.1
|
||||
========================
|
||||
|
||||
- New `odoo.domain` and `odoo.Domain` API for domain manipulation.
|
||||
See `#170009 <https://github.com/odoo/odoo/pull/170009>`_.
|
||||
- Declare constraints and indexes as model attributes with `#175783 <https://github.com/odoo/odoo/pull/175783>`_.
|
||||
- The `json` controllers have been renamed to `jsonrpc`. They are called the same, only the
|
||||
`type` in the python files changed. See `#183636 <https://github.com/odoo/odoo/pull/183636>`_.
|
||||
@ -21,7 +23,6 @@ Odoo version 18.0
|
||||
See `#179148 <https://github.com/odoo/odoo/pull/179148>`_.
|
||||
- Translations are made available from the `Environment` with `#174844 <https://github.com/odoo/odoo/pull/174844>`_.
|
||||
|
||||
|
||||
Odoo Online version 17.4
|
||||
========================
|
||||
|
||||
|
@ -245,6 +245,12 @@ less secure.
|
||||
'AND state=%s AND obj_price > 0', (tuple(ids), 'draft',))
|
||||
auction_lots_ids = [x[0] for x in self.env.cr.fetchall()]
|
||||
|
||||
# nearly there
|
||||
auction_lots_ids = [x[x] for x in self.env.execute_query(SQL("""
|
||||
SELECT id FROM auction_lots
|
||||
WHERE auction_id IN %s AND state = %s AND obj_price > 0
|
||||
""", tuple(ids), 'draft'))
|
||||
|
||||
# better
|
||||
auction_lots_ids = self.search([('auction_id','in',ids), ('state','=','draft'), ('obj_price','>',0)])
|
||||
|
||||
@ -266,6 +272,10 @@ database abstraction layer (psycopg2) to decide how to format query parameters,
|
||||
not your job! For example psycopg2 knows that when you pass a list of values
|
||||
it needs to format them as a comma-separated list, enclosed in parentheses !
|
||||
|
||||
Even better, there exists a :class:`~odoo.tools.SQL` wrapper to build queries
|
||||
using templates that handles the formatting of inputs.
|
||||
Check :ref:`SQL execution <reference/orm/sql>` for detailed usage.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# the following is very bad:
|
||||
@ -281,6 +291,13 @@ it needs to format them as a comma-separated list, enclosed in parentheses !
|
||||
'WHERE parent_id IN %s',
|
||||
(tuple(ids),))
|
||||
|
||||
# more readable
|
||||
self.env.cr.execute(SQL("""
|
||||
SELECT DISTINCT child_id
|
||||
FROM account_account_consol_rel
|
||||
WHERE parent_id IN %s
|
||||
""", tuple(ids)))
|
||||
|
||||
This is very important, so please be careful also when refactoring, and most
|
||||
importantly do not copy these patterns!
|
||||
|
||||
@ -293,6 +310,30 @@ online documentation of pyscopg2 to learn of to use it properly:
|
||||
- `Advanced parameter types <http://initd.org/psycopg/docs/usage.html#adaptation-of-python-values-to-sql-types>`_
|
||||
- `Psycopg documentation <https://www.psycopg.org/docs/sql.html>`_
|
||||
|
||||
Building the domains
|
||||
--------------------
|
||||
|
||||
Domains are represented as lists and are serializable.
|
||||
You would be tented to manipulate these lists directly, however it can
|
||||
introduce subtle issues where the user could inject a domain if the input is
|
||||
not normalized.
|
||||
Use :class:`~odoo.fields.Domain` to handle safely the manipulation
|
||||
of domains.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# bad
|
||||
# the user can just pass ['|', ('id', '>', 0)] to access all
|
||||
domain = ... # passed by the user
|
||||
security_domain = [('user_id', '=', self.env.uid)]
|
||||
domain += security_domain # can have a side-effect if this is a function argument
|
||||
self.search(domain)
|
||||
|
||||
# better
|
||||
domain = Domain(...)
|
||||
domain &= Domain('user_id', '=', self.env.uid)
|
||||
self.search(domain)
|
||||
|
||||
Unescaped field content
|
||||
-----------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user