summaryrefslogtreecommitdiff
path: root/odoo/api.py
diff options
context:
space:
mode:
authorVictor Feyens <vfe@odoo.com>2019-10-31 14:57:06 +0000
committerfw-bot <otis@odoo.com>2019-11-04 11:16:12 +0000
commitae4855fa1e0156cefdb1c31945252f2b7517a6f4 (patch)
tree324979856bbf49ed5ddae92f5fa5e1e5d631e48c /odoo/api.py
parentb2f3f092b726719159a16b4362c05592ba71360c (diff)
[IMP] base, doc: orm page refactoring.
closes odoo/odoo#39725 X-original-commit: 7ce7c58592c7c7202a37c73767c477be5a835752 Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Diffstat (limited to 'odoo/api.py')
-rw-r--r--odoo/api.py166
1 files changed, 79 insertions, 87 deletions
diff --git a/odoo/api.py b/odoo/api.py
index 931dc5ab149..f90bed82585 100644
--- a/odoo/api.py
+++ b/odoo/api.py
@@ -1,34 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-""" This module provides the elements for managing two different API styles,
- namely the "traditional" and "record" styles.
-
- In the "traditional" style, parameters like the database cursor, user id,
- context dictionary and record ids (usually denoted as ``cr``, ``uid``,
- ``context``, ``ids``) are passed explicitly to all methods. In the "record"
- style, those parameters are hidden into model instances, which gives it a
- more object-oriented feel.
-
- For instance, the statements::
-
- model = self.pool.get(MODEL)
- ids = model.search(cr, uid, DOMAIN, context=context)
- for rec in model.browse(cr, uid, ids, context=context):
- print rec.name
- model.write(cr, uid, ids, VALUES, context=context)
-
- may also be written as::
-
- env = Environment(cr, uid, context) # cr, uid, context wrapped in env
- model = env[MODEL] # retrieve an instance of MODEL
- recs = model.search(DOMAIN) # search returns a recordset
- for rec in recs: # iterate over the records
- print rec.name
- recs.write(VALUES) # update all records in recs
-
- Methods written in the "traditional" style are automatically decorated,
- following some heuristics based on parameter names.
+"""The Odoo API module defines Odoo Environments and method decorators.
+
+.. todo:: Document this module
"""
__all__ = [
@@ -124,8 +99,9 @@ def propagate(method1, method2):
def constrains(*args):
- """ Decorates a constraint checker. Each argument must be a field name
- used in the check::
+ """Decorate a constraint checker.
+
+ Each argument must be a field name used in the check::
@api.constrains('name', 'description')
def _check_description(self):
@@ -135,14 +111,14 @@ def constrains(*args):
Invoked on the records on which one of the named fields has been modified.
- Should raise :class:`~odoo.exceptions.ValidationError` if the
+ Should raise :exc:`~odoo.exceptions.ValidationError` if the
validation failed.
.. warning::
``@constrains`` only supports simple field names, dotted names
(fields of relational fields e.g. ``partner_id.customer``) are not
- supported and will be ignored
+ supported and will be ignored.
``@constrains`` will be triggered only if the declared fields in the
decorated method are included in the ``create`` or ``write`` call.
@@ -156,44 +132,51 @@ def constrains(*args):
def onchange(*args):
- """ Return a decorator to decorate an onchange method for given fields.
- Each argument must be a field name::
+ """Return a decorator to decorate an onchange method for given fields.
- @api.onchange('partner_id')
- def _onchange_partner(self):
- self.message = "Dear %s" % (self.partner_id.name or "")
+ In the form views where the field appears, the method will be called
+ when one of the given fields is modified. The method is invoked on a
+ pseudo-record that contains the values present in the form. Field
+ assignments on that record are automatically sent back to the client.
- In the form views where the field appears, the method will be called
- when one of the given fields is modified. The method is invoked on a
- pseudo-record that contains the values present in the form. Field
- assignments on that record are automatically sent back to the client.
+ Each argument must be a field name::
- The method may return a dictionary for changing field domains and pop up
- a warning message, like in the old API::
+ @api.onchange('partner_id')
+ def _onchange_partner(self):
+ self.message = "Dear %s" % (self.partner_id.name or "")
- return {
- 'domain': {'other_id': [('partner_id', '=', partner_id)]},
- 'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},
- }
- If the type is set to notification, the warning will be displayed in a notification.
- Otherwise it will be displayed in a dialog as default.
+ .. code-block:: python
- .. danger::
+ return {
+ 'domain': {'other_id': [('partner_id', '=', partner_id)]},
+ 'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},
+ }
- Since ``@onchange`` returns a recordset of pseudo-records,
- calling any one of the CRUD methods
- (:meth:`create`, :meth:`read`, :meth:`write`, :meth:`unlink`)
- on the aforementioned recordset is undefined behaviour,
- as they potentially do not exist in the database yet.
+ If the type is set to notification, the warning will be displayed in a notification.
+ Otherwise it will be displayed in a dialog as default.
- Instead, simply set the record's field like shown in the example
- above or call the :meth:`update` method.
+ .. warning::
- .. warning::
+ ``@onchange`` only supports simple field names, dotted names
+ (fields of relational fields e.g. ``partner_id.tz``) are not
+ supported and will be ignored
+
+ .. danger::
+
+ Since ``@onchange`` returns a recordset of pseudo-records,
+ calling any one of the CRUD methods
+ (:meth:`create`, :meth:`read`, :meth:`write`, :meth:`unlink`)
+ on the aforementioned recordset is undefined behaviour,
+ as they potentially do not exist in the database yet.
+
+ Instead, simply set the record's field like shown in the example
+ above or call the :meth:`update` method.
+
+ .. warning::
+
+ It is not possible for a ``one2many`` or ``many2many`` field to modify
+ itself via onchange. This is a webclient limitation - see `#2693 <https://github.com/odoo/odoo/issues/2693>`_.
- ``@onchange`` only supports simple field names, dotted names
- (fields of relational fields e.g. ``partner_id.tz``) are not
- supported and will be ignored
"""
return attrsetter('_onchange', args)
@@ -225,25 +208,26 @@ def depends(*args):
def depends_context(*args):
""" Return a decorator that specifies the context dependencies of a
- non-stored "compute" method. Each argument is a key in the context's
- dictionary::
+ non-stored "compute" method. Each argument is a key in the context's
+ dictionary::
- price = fields.Float(compute='_compute_product_price')
+ price = fields.Float(compute='_compute_product_price')
- @api.depends_context('pricelist')
- def _compute_product_price(self):
- for product in self:
- if product.env.context.get('pricelist'):
- pricelist = self.env['product.pricelist'].browse(product.env.context['pricelist'])
- else:
- pricelist = self.env['product.pricelist'].get_default_pricelist()
- product.price = pricelist.get_products_price(product).get(product.id, 0.0)
-
- All dependencies must be hashable. The following keys have special
- support:
- - 'force_company' (value in context or current company id),
- - 'uid' (current user id and superuser flag),
- - 'active_test' (value in env.context or value in field.context).
+ @api.depends_context('pricelist')
+ def _compute_product_price(self):
+ for product in self:
+ if product.env.context.get('pricelist'):
+ pricelist = self.env['product.pricelist'].browse(product.env.context['pricelist'])
+ else:
+ pricelist = self.env['product.pricelist'].get_default_pricelist()
+ product.price = pricelist.get_products_price(product).get(product.id, 0.0)
+
+ All dependencies must be hashable. The following keys have special
+ support:
+
+ * `force_company` (value in context or current company id),
+ * `uid` (current user id and superuser flag),
+ * `active_test` (value in env.context or value in field.context).
"""
return attrsetter('_depends_context', args)
@@ -510,6 +494,9 @@ class Environment(Mapping):
:param user: optional user/user id to change the current user
:param context: optional context dictionary to change the current context
:param su: optional boolean to change the superuser mode
+ :type context: dict
+ :type user: int or :class:`~odoo.addons.base.models.res_users`
+ :type su: bool
"""
cr = self.cr if cr is None else cr
uid = self.uid if user is None else int(user)
@@ -518,7 +505,7 @@ class Environment(Mapping):
return Environment(cr, uid, context, su)
def ref(self, xml_id, raise_if_not_found=True):
- """ return the record corresponding to the given ``xml_id`` """
+ """Return the record corresponding to the given ``xml_id``."""
return self['ir.model.data'].xmlid_to_object(xml_id, raise_if_not_found=raise_if_not_found)
def is_superuser(self):
@@ -537,17 +524,19 @@ class Environment(Mapping):
@lazy_property
def user(self):
- """ return the current user (as an instance) """
+ """Return the current user (as an instance).
+
+ :rtype: :class:`~odoo.addons.base.models.res_users`"""
return self(su=True)['res.users'].browse(self.uid)
@lazy_property
def company(self):
"""Return the current company (as an instance).
- If not specified in the context ('allowed_company_ids'),
- fallback on current user main company.
+ If not specified in the context (`allowed_company_ids`),
+ fallback on current user main company.
- :raise AccessError: invalid or unauthorized 'allowed_company_ids' context key content.
+ :raise AccessError: invalid or unauthorized `allowed_company_ids` context key content.
:return: current company (default=`self.user.company_id`)
:rtype: res.company
@@ -574,10 +563,10 @@ class Environment(Mapping):
def companies(self):
"""Return a recordset of the enabled companies by the user.
- If not specified in the context('allowed_company_ids'),
- fallback on current user companies.
+ If not specified in the context(`allowed_company_ids`),
+ fallback on current user companies.
- :raise AccessError: invalid or unauthorized 'allowed_company_ids' context key content.
+ :raise AccessError: invalid or unauthorized `allowed_company_ids` context key content.
:return: current companies (default=`self.user.company_ids`)
:rtype: res.company
@@ -612,7 +601,10 @@ class Environment(Mapping):
@property
def lang(self):
- """ return the current language code """
+ """Return the current language code.
+
+ :rtype: str
+ """
return self.context.get('lang')
def clear(self):