[IMP] doc: move old API sections to orm toplevel
also move porting checklist/doc/thing to bottom of document, it's mostly for seasoned or internal developers
This commit is contained in:
parent
c65ed4df76
commit
1338f3af35
|
@ -421,10 +421,31 @@ added.
|
|||
is not written to the database, just used to know which value to send back
|
||||
to the client
|
||||
|
||||
Low-level SQL
|
||||
-------------
|
||||
|
||||
The :attr:`~openerp.api.Environment.cr` attribute on environments is the
|
||||
cursor for the current database transaction and allows executing SQL directly,
|
||||
either for queries which are difficult to express using the ORM (e.g. complex
|
||||
joins) or for performance reasons::
|
||||
|
||||
self.env.cr.execute("some_sql", param1, param2, param3)
|
||||
|
||||
Because models use the same cursor and the :class:`~openerp.api.Environment`
|
||||
holds various caches, these caches must be invalidated when *altering* the
|
||||
database in raw SQL, or further uses of models may become incoherent. It is
|
||||
necessary to clear caches when using ``CREATE``, ``UPDATE`` or ``DELETE`` in
|
||||
SQL, but not ``SELECT`` (which simply reads the database).
|
||||
|
||||
Clearing caches can be performed using the
|
||||
:meth:`~openerp.api.Environment.invalidate_all` method of the
|
||||
:class:`~openerp.api.Environment` object.
|
||||
|
||||
|
||||
.. _reference/orm/oldapi:
|
||||
|
||||
Old API compatibility
|
||||
---------------------
|
||||
=====================
|
||||
|
||||
Odoo is currently transitioning from an older (less regular) API, it can be
|
||||
necessary to manually bridge from one to the other manually:
|
||||
|
@ -508,170 +529,6 @@ return lists of ids, there is also a decorator managing this:
|
|||
>>> old_style_model.some_method(cr, uid, [1, 2, 3], context=context)
|
||||
[1, 2, 3]
|
||||
|
||||
Porting from the old API
|
||||
------------------------
|
||||
|
||||
* methods still written in the old API should be automatically bridged by the
|
||||
ORM, no need to switch to the old API, just call them as if they were a new
|
||||
API method. See :ref:`reference/orm/oldapi/bridging` for more details.
|
||||
* ``search`` returns a recordset, no point in e.g. browsing its result
|
||||
* ``fields.related`` and ``fields.function`` are replaced by using a normal
|
||||
field type with either a ``related`` or a ``compute`` parameter
|
||||
* ``depends`` on field compute methods **must be complete**, it must list
|
||||
**all** the fields and sub-fields which the compute method uses. It is
|
||||
better to have too many dependencies (will recompute the field in cases
|
||||
where that is not needed) than not enough (will forget to recompute the
|
||||
field and then values will be incorrect)
|
||||
* **remove** all ``onchange`` methods on computed fields. Computed fields are
|
||||
automatically re-computed when one of their dependencies is changed, and
|
||||
that is used to auto-generate ``onchange`` by the client
|
||||
* the decorators :func:`~openerp.api.model` and :func:`~openerp.api.multi` are
|
||||
for bridging *when calling from the old API context*, for internal or pure
|
||||
new-api (e.g. compute) they are useless
|
||||
* remove :attr:`~openerp.models.Model._default`, replace by ``default=``
|
||||
parameter on corresponding fields
|
||||
* if a field's ``string`` is the titlecased version of the field name::
|
||||
|
||||
name = fields.Char(string="Name")
|
||||
|
||||
it is useless and should be removed
|
||||
* ``multi`` does not do anything on new API fields use the same ``compute``
|
||||
methods on all relevant fields for the same result
|
||||
* provide ``compute``, ``inverse`` and ``search`` methods by name (as a
|
||||
string), this makes them overridable (removes the need for an intermediate
|
||||
"trampoline" function)
|
||||
* double check that all fields and methods have different names, there is no
|
||||
warning in case of collision (because Python handles it before Odoo sees
|
||||
anything)
|
||||
* the normal new-api import is ``from openerp import fields, models``. If
|
||||
compatibility decorators are necessary, use ``from openerp import api,
|
||||
fields, models``
|
||||
* avoid the :func:`~openerp.api.one` decorator, it probably does not do what
|
||||
you expect
|
||||
* remove explicit definition of :attr:`~openerp.models.Model.create_uid`,
|
||||
:attr:`~openerp.models.Model.create_date`,
|
||||
:attr:`~openerp.models.Model.write_uid` and
|
||||
:attr:`~openerp.models.Model.write_date` fields: they are now created as
|
||||
regular "legitimate" fields, and can be read and written like any other
|
||||
field out-of-the-box
|
||||
* when straight conversion is impossible (semantics can not be bridged) or the
|
||||
"old API" version is not desirable and could be improved for the new API, it
|
||||
is possible to use completely different "old API" and "new API"
|
||||
implementations for the same method name using :func:`~openerp.api.v7` and
|
||||
:func:`~openerp.api.v8`. The method should first be defined using the
|
||||
old-API style and decorated with :func:`~openerp.api.v7`, it should then be
|
||||
re-defined using the exact same name but the new-API style and decorated
|
||||
with :func:`~openerp.api.v8`. Calls from an old-API context will be
|
||||
dispatched to the first implementation and calls from a new-API context will
|
||||
be dispatched to the second implementation. One implementation can call (and
|
||||
frequently does) call the other by switching context.
|
||||
|
||||
.. danger:: using these decorators makes methods extremely difficult to
|
||||
override and harder to understand and document
|
||||
* uses of :attr:`~openerp.models.Model._columns` or
|
||||
:attr:`~openerp.models.Model._all_columns` should be replaced by
|
||||
:attr:`~openerp.models.Model._fields`, which provides access to instances of
|
||||
new-style :class:`openerp.fields.Field` instances (rather than old-style
|
||||
:class:`openerp.osv.fields._column`).
|
||||
|
||||
Non-stored computed fields created using the new API style are *not*
|
||||
available in :attr:`~openerp.models.Model._columns` and can only be
|
||||
inspected through :attr:`~openerp.models.Model._fields`
|
||||
* reassigning ``self`` in a method is probably unnecessary and may break
|
||||
translation introspection
|
||||
* :class:`~openerp.api.Environment` objects rely on some threadlocal state,
|
||||
which has to be set up before using them. It is necessary to do so using the
|
||||
:meth:`openerp.api.Environment.manage` context manager when trying to use
|
||||
the new API in contexts where it hasn't been set up yet, such as new threads
|
||||
or a Python interactive environment::
|
||||
|
||||
>>> from openerp import api, modules
|
||||
>>> r = modules.registry.RegistryManager.get('test')
|
||||
>>> cr = r.cursor()
|
||||
>>> env = api.Environment(cr, 1, {})
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: environments
|
||||
>>> with api.Environment.manage():
|
||||
... env = api.Environment(cr, 1, {})
|
||||
... print env['res.partner'].browse(1)
|
||||
...
|
||||
res.partner(1,)
|
||||
|
||||
.. _reference/orm/oldapi/bridging:
|
||||
|
||||
Automatic bridging of old API methods
|
||||
'''''''''''''''''''''''''''''''''''''
|
||||
|
||||
When models are initialized, all methods are automatically scanned and bridged
|
||||
if they look like models declared in the old API style. This bridging makes
|
||||
them transparently callable from new-API-style methods.
|
||||
|
||||
Methods are matched as "old-API style" if their second positional parameter
|
||||
(after ``self``) is called either ``cr`` or ``cursor``. The system also
|
||||
recognizes the third positional parameter being called ``uid`` or ``user`` and
|
||||
the fourth being called ``id`` or ``ids``. It also recognizes the presence of
|
||||
any parameter called ``context``.
|
||||
|
||||
When calling such methods from a new API context, the system will
|
||||
automatically fill matched parameters from the current
|
||||
:class:`~openerp.api.Environment` (for :attr:`~openerp.api.Environment.cr`,
|
||||
:attr:`~openerp.api.Environment.user` and
|
||||
:attr:`~openerp.api.Environment.context`) or the current recordset (for ``id``
|
||||
and ``ids``).
|
||||
|
||||
In the rare cases where it is necessary, the bridging can be customized by
|
||||
decorating the old-style method:
|
||||
|
||||
* disabling it entirely, by decorating a method with
|
||||
:func:`~openerp.api.noguess` there will be no bridging and methods will be
|
||||
called the exact same way from the new and old API styles
|
||||
* defining the bridge explicitly, this is mostly for methods which are matched
|
||||
incorrectly (because parameters are named in unexpected ways):
|
||||
|
||||
:func:`~openerp.api.cr`
|
||||
will automatically prepend the current cursor to explicitly provided
|
||||
parameters, positionally
|
||||
:func:`~openerp.api.cr_uid`
|
||||
will automatically prepend the current cursor and user's id to explictly
|
||||
provided parameters
|
||||
:func:`~openerp.api.cr_uid_ids`
|
||||
will automatically prepend the current cursor, user's id and recordset's
|
||||
ids to explicitly provided parameters
|
||||
:func:`~openerp.api.cr_uid_id`
|
||||
will loop over the current recordset and call the method once for each
|
||||
record, prepending the current cursor, user's id and record's id to
|
||||
explicitly provided parameters.
|
||||
|
||||
.. danger:: the result of this wrapper is *always a list* when calling
|
||||
from a new-API context
|
||||
|
||||
All of these methods have a ``_context``-suffixed version
|
||||
(e.g. :func:`~openerp.api.cr_uid_context`) which also passes the current
|
||||
context *by keyword*.
|
||||
* dual implementations using :func:`~openerp.api.v7` and
|
||||
:func:`~openerp.api.v8` will be ignored as they provide their own "bridging"
|
||||
|
||||
Low-level SQL
|
||||
-------------
|
||||
|
||||
The :attr:`~openerp.api.Environment.cr` attribute on environments is the
|
||||
cursor for the current database transaction and allows executing SQL directly,
|
||||
either for queries which are difficult to express using the ORM (e.g. complex
|
||||
joins) or for performance reasons::
|
||||
|
||||
self.env.cr.execute("some_sql", param1, param2, param3)
|
||||
|
||||
Because models use the same cursor and the :class:`~openerp.api.Environment`
|
||||
holds various caches, these caches must be invalidated when *altering* the
|
||||
database in raw SQL, or further uses of models may become incoherent. It is
|
||||
necessary to clear caches when using ``CREATE``, ``UPDATE`` or ``DELETE`` in
|
||||
SQL, but not ``SELECT`` (which simply reads the database).
|
||||
|
||||
Clearing caches can be performed using the
|
||||
:meth:`~openerp.api.Environment.invalidate_all` method of the
|
||||
:class:`~openerp.api.Environment` object.
|
||||
|
||||
.. _reference/orm/model:
|
||||
|
||||
Model Reference
|
||||
|
@ -1168,3 +1025,147 @@ Domain criteria can be combined using logical operators in *prefix* form:
|
|||
(name is 'ABC')
|
||||
AND (language is NOT english)
|
||||
AND (country is Belgium OR Germany)
|
||||
|
||||
Porting from the old API
|
||||
========================
|
||||
|
||||
* methods still written in the old API should be automatically bridged by the
|
||||
ORM, no need to switch to the old API, just call them as if they were a new
|
||||
API method. See :ref:`reference/orm/oldapi/bridging` for more details.
|
||||
* ``search`` returns a recordset, no point in e.g. browsing its result
|
||||
* ``fields.related`` and ``fields.function`` are replaced by using a normal
|
||||
field type with either a ``related`` or a ``compute`` parameter
|
||||
* ``depends`` on field compute methods **must be complete**, it must list
|
||||
**all** the fields and sub-fields which the compute method uses. It is
|
||||
better to have too many dependencies (will recompute the field in cases
|
||||
where that is not needed) than not enough (will forget to recompute the
|
||||
field and then values will be incorrect)
|
||||
* **remove** all ``onchange`` methods on computed fields. Computed fields are
|
||||
automatically re-computed when one of their dependencies is changed, and
|
||||
that is used to auto-generate ``onchange`` by the client
|
||||
* the decorators :func:`~openerp.api.model` and :func:`~openerp.api.multi` are
|
||||
for bridging *when calling from the old API context*, for internal or pure
|
||||
new-api (e.g. compute) they are useless
|
||||
* remove :attr:`~openerp.models.Model._default`, replace by ``default=``
|
||||
parameter on corresponding fields
|
||||
* if a field's ``string`` is the titlecased version of the field name::
|
||||
|
||||
name = fields.Char(string="Name")
|
||||
|
||||
it is useless and should be removed
|
||||
* ``multi`` does not do anything on new API fields use the same ``compute``
|
||||
methods on all relevant fields for the same result
|
||||
* provide ``compute``, ``inverse`` and ``search`` methods by name (as a
|
||||
string), this makes them overridable (removes the need for an intermediate
|
||||
"trampoline" function)
|
||||
* double check that all fields and methods have different names, there is no
|
||||
warning in case of collision (because Python handles it before Odoo sees
|
||||
anything)
|
||||
* the normal new-api import is ``from openerp import fields, models``. If
|
||||
compatibility decorators are necessary, use ``from openerp import api,
|
||||
fields, models``
|
||||
* avoid the :func:`~openerp.api.one` decorator, it probably does not do what
|
||||
you expect
|
||||
* remove explicit definition of :attr:`~openerp.models.Model.create_uid`,
|
||||
:attr:`~openerp.models.Model.create_date`,
|
||||
:attr:`~openerp.models.Model.write_uid` and
|
||||
:attr:`~openerp.models.Model.write_date` fields: they are now created as
|
||||
regular "legitimate" fields, and can be read and written like any other
|
||||
field out-of-the-box
|
||||
* when straight conversion is impossible (semantics can not be bridged) or the
|
||||
"old API" version is not desirable and could be improved for the new API, it
|
||||
is possible to use completely different "old API" and "new API"
|
||||
implementations for the same method name using :func:`~openerp.api.v7` and
|
||||
:func:`~openerp.api.v8`. The method should first be defined using the
|
||||
old-API style and decorated with :func:`~openerp.api.v7`, it should then be
|
||||
re-defined using the exact same name but the new-API style and decorated
|
||||
with :func:`~openerp.api.v8`. Calls from an old-API context will be
|
||||
dispatched to the first implementation and calls from a new-API context will
|
||||
be dispatched to the second implementation. One implementation can call (and
|
||||
frequently does) call the other by switching context.
|
||||
|
||||
.. danger:: using these decorators makes methods extremely difficult to
|
||||
override and harder to understand and document
|
||||
* uses of :attr:`~openerp.models.Model._columns` or
|
||||
:attr:`~openerp.models.Model._all_columns` should be replaced by
|
||||
:attr:`~openerp.models.Model._fields`, which provides access to instances of
|
||||
new-style :class:`openerp.fields.Field` instances (rather than old-style
|
||||
:class:`openerp.osv.fields._column`).
|
||||
|
||||
Non-stored computed fields created using the new API style are *not*
|
||||
available in :attr:`~openerp.models.Model._columns` and can only be
|
||||
inspected through :attr:`~openerp.models.Model._fields`
|
||||
* reassigning ``self`` in a method is probably unnecessary and may break
|
||||
translation introspection
|
||||
* :class:`~openerp.api.Environment` objects rely on some threadlocal state,
|
||||
which has to be set up before using them. It is necessary to do so using the
|
||||
:meth:`openerp.api.Environment.manage` context manager when trying to use
|
||||
the new API in contexts where it hasn't been set up yet, such as new threads
|
||||
or a Python interactive environment::
|
||||
|
||||
>>> from openerp import api, modules
|
||||
>>> r = modules.registry.RegistryManager.get('test')
|
||||
>>> cr = r.cursor()
|
||||
>>> env = api.Environment(cr, 1, {})
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: environments
|
||||
>>> with api.Environment.manage():
|
||||
... env = api.Environment(cr, 1, {})
|
||||
... print env['res.partner'].browse(1)
|
||||
...
|
||||
res.partner(1,)
|
||||
|
||||
.. _reference/orm/oldapi/bridging:
|
||||
|
||||
Automatic bridging of old API methods
|
||||
-------------------------------------
|
||||
|
||||
When models are initialized, all methods are automatically scanned and bridged
|
||||
if they look like models declared in the old API style. This bridging makes
|
||||
them transparently callable from new-API-style methods.
|
||||
|
||||
Methods are matched as "old-API style" if their second positional parameter
|
||||
(after ``self``) is called either ``cr`` or ``cursor``. The system also
|
||||
recognizes the third positional parameter being called ``uid`` or ``user`` and
|
||||
the fourth being called ``id`` or ``ids``. It also recognizes the presence of
|
||||
any parameter called ``context``.
|
||||
|
||||
When calling such methods from a new API context, the system will
|
||||
automatically fill matched parameters from the current
|
||||
:class:`~openerp.api.Environment` (for :attr:`~openerp.api.Environment.cr`,
|
||||
:attr:`~openerp.api.Environment.user` and
|
||||
:attr:`~openerp.api.Environment.context`) or the current recordset (for ``id``
|
||||
and ``ids``).
|
||||
|
||||
In the rare cases where it is necessary, the bridging can be customized by
|
||||
decorating the old-style method:
|
||||
|
||||
* disabling it entirely, by decorating a method with
|
||||
:func:`~openerp.api.noguess` there will be no bridging and methods will be
|
||||
called the exact same way from the new and old API styles
|
||||
* defining the bridge explicitly, this is mostly for methods which are matched
|
||||
incorrectly (because parameters are named in unexpected ways):
|
||||
|
||||
:func:`~openerp.api.cr`
|
||||
will automatically prepend the current cursor to explicitly provided
|
||||
parameters, positionally
|
||||
:func:`~openerp.api.cr_uid`
|
||||
will automatically prepend the current cursor and user's id to explictly
|
||||
provided parameters
|
||||
:func:`~openerp.api.cr_uid_ids`
|
||||
will automatically prepend the current cursor, user's id and recordset's
|
||||
ids to explicitly provided parameters
|
||||
:func:`~openerp.api.cr_uid_id`
|
||||
will loop over the current recordset and call the method once for each
|
||||
record, prepending the current cursor, user's id and record's id to
|
||||
explicitly provided parameters.
|
||||
|
||||
.. danger:: the result of this wrapper is *always a list* when calling
|
||||
from a new-API context
|
||||
|
||||
All of these methods have a ``_context``-suffixed version
|
||||
(e.g. :func:`~openerp.api.cr_uid_context`) which also passes the current
|
||||
context *by keyword*.
|
||||
* dual implementations using :func:`~openerp.api.v7` and
|
||||
:func:`~openerp.api.v8` will be ignored as they provide their own "bridging"
|
||||
|
|
Loading…
Reference in New Issue