diff --git a/content/developer/misc/api/iap.rst b/content/developer/misc/api/iap.rst index f9e5537ca..b98ae7527 100644 --- a/content/developer/misc/api/iap.rst +++ b/content/developer/misc/api/iap.rst @@ -1,5 +1,5 @@ -.. _webservices/iap: +.. _api/iap: =============== In-App Purchase diff --git a/content/developer/misc/api/odoo.rst b/content/developer/misc/api/odoo.rst index 17c5c7e74..cd4dd5827 100644 --- a/content/developer/misc/api/odoo.rst +++ b/content/developer/misc/api/odoo.rst @@ -1,5 +1,3 @@ -:code-column: - ============ External API ============ @@ -9,88 +7,15 @@ all of its data are also available from the outside for external analysis or integration with various tools. Part of the :ref:`reference/orm/model` API is easily available over XML-RPC_ and accessible from a variety of languages. -.. Odoo XML-RPC idiosyncrasies: - * uses multiple endpoint and a nested call syntax instead of a - "hierarchical" server structure (e.g. ``odoo.res.partner.read()``) - * uses its own own manual auth system instead of basic auth or sessions - (basic is directly supported the Python and Ruby stdlibs as well as - ws-xmlrpc, not sure about ripcord) - * own auth is inconvenient as (uid, password) have to be explicitly passed - into every call. Session would allow db to be stored as well - These issues are especially visible in Java, somewhat less so in PHP - Connection ========== -.. kinda gross because it duplicates existing bits - -.. only:: html - - .. rst-class:: setupcode hidden - - .. code-block:: python3 - - import xmlrpc.client - info = xmlrpc.client.ServerProxy('https://demo.odoo.com/start').start() - url, db, username, password = \ - info['host'], info['database'], info['user'], info['password'] - common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url)) - uid = common.authenticate(db, username, password, {}) - models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url)) - - .. code-block:: ruby - - require "xmlrpc/client" - info = XMLRPC::Client.new2('https://demo.odoo.com/start').call('start') - url, db, username, password = \ - info['host'], info['database'], info['user'], info['password'] - common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common") - uid = common.call('authenticate', db, username, password, {}) - models = XMLRPC::Client.new2("#{url}/xmlrpc/2/object").proxy - - .. code-block:: php - - require_once('ripcord.php'); - $info = ripcord::client('https://demo.odoo.com/start')->start(); - list($url, $db, $username, $password) = - array($info['host'], $info['database'], $info['user'], $info['password']); - $common = ripcord::client("$url/xmlrpc/2/common"); - $uid = $common->authenticate($db, $username, $password, array()); - $models = ripcord::client("$url/xmlrpc/2/object"); - - .. code-block:: java - - final XmlRpcClient client = new XmlRpcClient(); - final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl(); - start_config.setServerURL(new URL("https://demo.odoo.com/start")); - final Map info = (Map)client.execute( - start_config, "start", emptyList()); - - final String url = info.get("host"), - db = info.get("database"), - username = info.get("user"), - password = info.get("password"); - - final XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl(); - common_config.setServerURL(new URL(String.format("%s/xmlrpc/2/common", url))); - - int uid = (int)client.execute( - common_config, "authenticate", Arrays.asList( - db, username, password, emptyMap())); - - final XmlRpcClient models = new XmlRpcClient() {{ - setConfig(new XmlRpcClientConfigImpl() {{ - setServerURL(new URL(String.format("%s/xmlrpc/2/object", url))); - }}); - }}; - Configuration ------------- -If you already have an Odoo server installed, you can just use its -parameters +If you already have an Odoo server installed, you can just use its parameters. -.. warning:: +.. important:: For Odoo Online instances (.odoo.com), users are created without a *local* password (as a person you are logged in via the Odoo Online @@ -98,52 +23,49 @@ parameters Online instances, you will need to set a password on the user account you want to use: - * Log in your instance with an administrator account - * Go to :menuselection:`Settings --> Users & Companies --> Users` - * Click on the user you want to use for XML-RPC access - * Click on :guilabel:`Action` and select :guilabel:`Change Password` - * Set a :guilabel:`New Password` value then click - :guilabel:`Change Password`. + * Log in your instance with an administrator account. + * Go to :menuselection:`Settings --> Users & Companies --> Users`. + * Click on the user you want to use for XML-RPC access. + * Click on :guilabel:`Action` and select :guilabel:`Change Password`. + * Set a :guilabel:`New Password` value then click :guilabel:`Change Password`. The *server url* is the instance's domain (e.g. *https://mycompany.odoo.com*), the *database name* is the name of the instance (e.g. *mycompany*). The *username* is the configured user's login as shown by the *Change Password* screen. -.. rst-class:: setup doc-aside +.. tabs:: -.. switcher:: + .. code-tab:: python - .. code-block:: python3 + url = + db = + username = 'admin' + password = - url = - db = - username = 'admin' - password = + .. code-tab:: ruby - .. code-block:: ruby + url = + db = + username = "admin" + password = - url = - db = - username = "admin" - password = + .. code-tab:: php - .. code-block:: php + $url = ; + $db = ; + $username = "admin"; + $password = ; - $url = ; - $db = ; - $username = "admin"; - $password = ; + .. code-tab:: java - .. code-block:: java - - final String url = , - db = , - username = "admin", - password = ; + final String url = , + db = , + username = "admin", + password = ; API Keys -'''''''' +~~~~~~~~ .. versionadded:: 14.0 @@ -158,14 +80,14 @@ account (although they can not be used to log-in via the interface). In order to add a key to your account, simply go to your :guilabel:`Preferences` (or :guilabel:`My Profile`): -.. figure:: images/preferences.png - :align: center +.. image:: images/preferences.png + :align: center then open the :guilabel:`Account Security` tab, and click :guilabel:`New API Key`: -.. figure:: images/account-security.png - :align: center +.. image:: images/account-security.png + :align: center Input a description for the key, **this description should be as clear and complete as possible**: it is the only way you will have to identify your keys @@ -180,81 +102,73 @@ lost). Once you have keys configured on your account, they will appear above the :guilabel:`New API Key` button, and you will be able to delete them: -.. figure:: images/delete-key.png - :align: center +.. image:: images/delete-key.png + :align: center **A deleted API key can not be undeleted or re-set**. You will have to generate a new key and update all the places where you used the old one. -demo -'''' +Test database +~~~~~~~~~~~~~ To make exploration simpler, you can also ask https://demo.odoo.com for a test database: -.. rst-class:: setup doc-aside +.. tabs:: -.. switcher:: + .. code-tab:: python - .. code-block:: python3 + import xmlrpc.client + info = xmlrpc.client.ServerProxy('https://demo.odoo.com/start').start() + url, db, username, password = info['host'], info['database'], info['user'], info['password'] - import xmlrpc.client - info = xmlrpc.client.ServerProxy('https://demo.odoo.com/start').start() - url, db, username, password = \ - info['host'], info['database'], info['user'], info['password'] + .. code-tab:: ruby - .. code-block:: ruby + require "xmlrpc/client" + info = XMLRPC::Client.new2('https://demo.odoo.com/start').call('start') + url, db, username, password = info['host'], info['database'], info['user'], info['password'] - require "xmlrpc/client" - info = XMLRPC::Client.new2('https://demo.odoo.com/start').call('start') - url, db, username, password = \ - info['host'], info['database'], info['user'], info['password'] + .. group-tab:: PHP - .. case:: PHP + .. code-block:: php - .. code-block:: php + require_once('ripcord.php'); + $info = ripcord::client('https://demo.odoo.com/start')->start(); + list($url, $db, $username, $password) = array($info['host'], $info['database'], $info['user'], $info['password']); - require_once('ripcord.php'); - $info = ripcord::client('https://demo.odoo.com/start')->start(); - list($url, $db, $username, $password) = - array($info['host'], $info['database'], $info['user'], $info['password']); + .. note:: + These examples use the `Ripcord `_ + library, which provides a simple XML-RPC API. Ripcord requires that + `XML-RPC support be enabled + `_ in your PHP + installation. - .. note:: + Since calls are performed over + `HTTPS `_, it also requires that + the `OpenSSL extension + `_ be enabled. - These examples use the `Ripcord `_ - library, which provides a simple XML-RPC API. Ripcord requires that - `XML-RPC support be enabled - `_ in your PHP - installation. + .. group-tab:: Java - Since calls are performed over - `HTTPS `_, it also requires that - the `OpenSSL extension - `_ be enabled. + .. code-block:: java - .. case:: Java + final XmlRpcClient client = new XmlRpcClient(); - .. code-block:: java + final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl(); + start_config.setServerURL(new URL("https://demo.odoo.com/start")); + final Map info = (Map)client.execute( + start_config, "start", emptyList()); - final XmlRpcClient client = new XmlRpcClient(); + final String url = info.get("host"), + db = info.get("database"), + username = info.get("user"), + password = info.get("password"); - final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl(); - start_config.setServerURL(new URL("https://demo.odoo.com/start")); - final Map info = (Map)client.execute( - start_config, "start", emptyList()); + .. note:: + These examples use the `Apache XML-RPC library `_. - final String url = info.get("host"), - db = info.get("database"), - username = info.get("user"), - password = info.get("password"); - - .. note:: - - These examples use the `Apache XML-RPC library - `_ - - The examples do not include imports as these imports couldn't be - pasted in the code. + The examples do not include imports as these imports couldn't be + pasted in the code. Logging in ---------- @@ -270,71 +184,65 @@ authentication itself is done through the ``authenticate`` function and returns a user identifier (``uid``) used in authenticated calls instead of the login. -.. rst-class:: setup doc-aside +.. tabs:: -.. switcher:: + .. code-tab:: python - .. code-block:: python3 + common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url)) + common.version() - common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url)) - common.version() + .. code-tab:: ruby - .. code-block:: ruby + common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common") + common.call('version') - common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common") - common.call('version') + .. code-tab:: php - .. code-block:: php + $common = ripcord::client("$url/xmlrpc/2/common"); + $common->version(); - $common = ripcord::client("$url/xmlrpc/2/common"); - $common->version(); + .. code-tab:: java - .. code-block:: java + final XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl(); + common_config.setServerURL(new URL(String.format("%s/xmlrpc/2/common", url))); + client.execute(common_config, "version", emptyList()); - final XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl(); - common_config.setServerURL( - new URL(String.format("%s/xmlrpc/2/common", url))); - client.execute(common_config, "version", emptyList()); - -.. rst-class:: doc-aside +Result: .. code-block:: json - { - "server_version": "13.0", - "server_version_info": [13, 0, 0, "final", 0], - "server_serie": "13.0", - "protocol_version": 1, - } + { + "server_version": "13.0", + "server_version_info": [13, 0, 0, "final", 0], + "server_serie": "13.0", + "protocol_version": 1, + } -.. rst-class:: setup doc-aside -.. switcher:: +.. tabs:: - .. code-block:: python3 + .. code-tab:: python - uid = common.authenticate(db, username, password, {}) + uid = common.authenticate(db, username, password, {}) - .. code-block:: ruby + .. code-tab:: ruby - uid = common.call('authenticate', db, username, password, {}) + uid = common.call('authenticate', db, username, password, {}) - .. code-block:: php + .. code-tab:: php - $uid = $common->authenticate($db, $username, $password, array()); + $uid = $common->authenticate($db, $username, $password, array()); - .. code-block:: java + .. code-tab:: java - int uid = (int)client.execute( - common_config, "authenticate", asList( - db, username, password, emptyMap())); + int uid = (int)client.execute(common_config, "authenticate", asList(db, username, password, emptyMap())); -.. _webservices/odoo/calling_methods: +.. _api/odoo/calling_methods: Calling methods =============== -The second endpoint is ``xmlrpc/2/object``, is used to call methods of odoo +The second endpoint is ``xmlrpc/2/object``. It is used to call methods of odoo models via the ``execute_kw`` RPC function. Each call to ``execute_kw`` takes the following parameters: @@ -347,57 +255,49 @@ Each call to ``execute_kw`` takes the following parameters: * an array/list of parameters passed by position * a mapping/dict of parameters to pass by keyword (optional) -.. container:: doc-aside +.. example:: - For instance to see if we can read the ``res.partner`` model we can call - ``check_access_rights`` with ``operation`` passed by position and - ``raise_exception`` passed by keyword (in order to get a true/false result - rather than true/error): + For instance, to see if we can read the ``res.partner`` model, we can call + ``check_access_rights`` with ``operation`` passed by position and + ``raise_exception`` passed by keyword (in order to get a true/false result + rather than true/error): - .. rst-class:: setup + .. tabs:: - .. switcher:: + .. code-tab:: python - .. code-block:: python3 + models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url)) + models.execute_kw(db, uid, password, 'res.partner', 'check_access_rights', ['read'], {'raise_exception': False}) - models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url)) - models.execute_kw(db, uid, password, - 'res.partner', 'check_access_rights', - ['read'], {'raise_exception': False}) + .. code-tab:: ruby - .. code-block:: ruby + models = XMLRPC::Client.new2("#{url}/xmlrpc/2/object").proxy + models.execute_kw(db, uid, password, 'res.partner', 'check_access_rights', ['read'], {raise_exception: false}) - models = XMLRPC::Client.new2("#{url}/xmlrpc/2/object").proxy - models.execute_kw(db, uid, password, - 'res.partner', 'check_access_rights', - ['read'], {raise_exception: false}) + .. code-tab:: php - .. code-block:: php + $models = ripcord::client("$url/xmlrpc/2/object"); + $models->execute_kw($db, $uid, $password, 'res.partner', 'check_access_rights', array('read'), array('raise_exception' => false)); - $models = ripcord::client("$url/xmlrpc/2/object"); - $models->execute_kw($db, $uid, $password, - 'res.partner', 'check_access_rights', - array('read'), array('raise_exception' => false)); + .. code-tab:: java - .. code-block:: java + final XmlRpcClient models = new XmlRpcClient() {{ + setConfig(new XmlRpcClientConfigImpl() {{ + setServerURL(new URL(String.format("%s/xmlrpc/2/object", url))); + }}); + }}; + models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "check_access_rights", + asList("read"), + new HashMap() {{ put("raise_exception", false); }} + )); - final XmlRpcClient models = new XmlRpcClient() {{ - setConfig(new XmlRpcClientConfigImpl() {{ - setServerURL(new URL(String.format("%s/xmlrpc/2/object", url))); - }}); - }}; - models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "check_access_rights", - asList("read"), - new HashMap() {{ put("raise_exception", false); }} - )); + Result: - .. code-block:: json + .. code-block:: json - true - - .. todo:: this should be runnable and checked + true List records ------------ @@ -406,89 +306,79 @@ Records can be listed and filtered via :meth:`~odoo.models.Model.search`. :meth:`~odoo.models.Model.search` takes a mandatory :ref:`domain ` filter (possibly empty), and returns the -database identifiers of all records matching the filter. To list customer -companies for instance: +database identifiers of all records matching the filter. -.. container:: doc-aside +.. example:: - .. switcher:: + To list customer companies, for instance: - .. code-block:: python3 + .. tabs:: - models.execute_kw(db, uid, password, - 'res.partner', 'search', - [[['is_company', '=', True]]]) + .. code-tab:: python - .. code-block:: ruby + models.execute_kw(db, uid, password, 'res.partner', 'search', [[['is_company', '=', True]]]) - models.execute_kw(db, uid, password, - 'res.partner', 'search', - [[['is_company', '=', true]]]) + .. code-tab:: ruby - .. code-block:: php + models.execute_kw(db, uid, password, 'res.partner', 'search', [[['is_company', '=', true]]]) - $models->execute_kw($db, $uid, $password, - 'res.partner', 'search', array( - array(array('is_company', '=', true)))); + .. code-tab:: php - .. code-block:: java + $models->execute_kw($db, $uid, $password, 'res.partner', 'search', array(array(array('is_company', '=', true)))); - asList((Object[])models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "search", - asList(asList( - asList("is_company", "=", true))) - ))); + .. code-tab:: java - .. code-block:: json + asList((Object[])models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "search", + asList(asList( + asList("is_company", "=", true))) + ))); - [7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74] + Result: + + .. code-block:: json + + [7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74] Pagination -'''''''''' +~~~~~~~~~~ By default a search will return the ids of all records matching the condition, which may be a huge number. ``offset`` and ``limit`` parameters are available to only retrieve a subset of all matched records. -.. container:: doc-aside +.. example:: - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - models.execute_kw(db, uid, password, - 'res.partner', 'search', - [[['is_company', '=', True]]], - {'offset': 10, 'limit': 5}) + models.execute_kw(db, uid, password, 'res.partner', 'search', [[['is_company', '=', True]]], {'offset': 10, 'limit': 5}) - .. code-block:: ruby + .. code-tab:: ruby - models.execute_kw(db, uid, password, - 'res.partner', 'search', - [[['is_company', '=', true]]], - {offset: 10, limit: 5}) + models.execute_kw(db, uid, password, 'res.partner', 'search', [[['is_company', '=', true]]], {offset: 10, limit: 5}) - .. code-block:: php + .. code-tab:: php - $models->execute_kw($db, $uid, $password, - 'res.partner', 'search', - array(array(array('is_company', '=', true))), - array('offset'=>10, 'limit'=>5)); + $models->execute_kw($db, $uid, $password, 'res.partner', 'search', array(array(array('is_company', '=', true))), array('offset'=>10, 'limit'=>5)); - .. code-block:: java + .. code-tab:: java - asList((Object[])models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "search", - asList(asList( - asList("is_company", "=", true))), - new HashMap() {{ put("offset", 10); put("limit", 5); }} - ))); + asList((Object[])models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "search", + asList(asList( + asList("is_company", "=", true))), + new HashMap() {{ put("offset", 10); put("limit", 5); }} + ))); - .. code-block:: json + Result: - [13, 20, 30, 22, 29] + .. code-block:: json + + [13, 20, 30, 22, 29] Count records ------------- @@ -499,160 +389,139 @@ only the number of records matching the query. It takes the same :ref:`domain ` filter as :meth:`~odoo.models.Model.search` and no other parameter. -.. container:: doc-aside +.. example:: - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - models.execute_kw(db, uid, password, - 'res.partner', 'search_count', - [[['is_company', '=', True]]]) + models.execute_kw(db, uid, password, 'res.partner', 'search_count', [[['is_company', '=', True]]]) - .. code-block:: ruby + .. code-tab:: ruby - models.execute_kw(db, uid, password, - 'res.partner', 'search_count', - [[['is_company', '=', true]]]) + models.execute_kw(db, uid, password, 'res.partner', 'search_count', [[['is_company', '=', true]]]) - .. code-block:: php + .. code-tab:: php - $models->execute_kw($db, $uid, $password, - 'res.partner', 'search_count', - array(array(array('is_company', '=', true)))); + $models->execute_kw($db, $uid, $password, 'res.partner', 'search_count', array(array(array('is_company', '=', true)))); - .. code-block:: java + .. code-tab:: java - (Integer)models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "search_count", - asList(asList( - asList("is_company", "=", true))) - )); + (Integer)models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "search_count", + asList(asList( + asList("is_company", "=", true))) + )); - .. code-block:: json + Result: - 19 + .. code-block:: json -.. warning:: + 19 - calling ``search`` then ``search_count`` (or the other way around) may not - yield coherent results if other users are using the server: stored data - could have changed between the calls +.. note:: + Calling ``search`` then ``search_count`` (or the other way around) may not + yield coherent results if other users are using the server: stored data + could have changed between the calls. Read records ------------ -Record data is accessible via the :meth:`~odoo.models.Model.read` method, +Record data are accessible via the :meth:`~odoo.models.Model.read` method, which takes a list of ids (as returned by -:meth:`~odoo.models.Model.search`) and optionally a list of fields to -fetch. By default, it will fetch all the fields the current user can read, +:meth:`~odoo.models.Model.search`), and optionally a list of fields to +fetch. By default, it fetches all the fields the current user can read, which tends to be a huge amount. -.. container:: doc-aside +.. example:: - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - ids = models.execute_kw(db, uid, password, - 'res.partner', 'search', - [[['is_company', '=', True]]], - {'limit': 1}) - [record] = models.execute_kw(db, uid, password, - 'res.partner', 'read', [ids]) - # count the number of fields fetched by default - len(record) + ids = models.execute_kw(db, uid, password, 'res.partner', 'search', [[['is_company', '=', True]]], {'limit': 1}) + [record] = models.execute_kw(db, uid, password, 'res.partner', 'read', [ids]) + # count the number of fields fetched by default + len(record) - .. code-block:: ruby + .. code-tab:: ruby - ids = models.execute_kw(db, uid, password, - 'res.partner', 'search', - [[['is_company', '=', true]]], - {limit: 1}) - record = models.execute_kw(db, uid, password, - 'res.partner', 'read', [ids]).first - # count the number of fields fetched by default - record.length + ids = models.execute_kw(db, uid, password, 'res.partner', 'search', [[['is_company', '=', true]]], {limit: 1}) + record = models.execute_kw(db, uid, password, 'res.partner', 'read', [ids]).first + # count the number of fields fetched by default + record.length - .. code-block:: php + .. code-tab:: php - $ids = $models->execute_kw($db, $uid, $password, - 'res.partner', 'search', - array(array(array('is_company', '=', true))), - array('limit'=>1)); - $records = $models->execute_kw($db, $uid, $password, - 'res.partner', 'read', array($ids)); - // count the number of fields fetched by default - count($records[0]); + $ids = $models->execute_kw($db, $uid, $password, 'res.partner', 'search', array(array(array('is_company', '=', true))), array('limit'=>1)); + $records = $models->execute_kw($db, $uid, $password, 'res.partner', 'read', array($ids)); + // count the number of fields fetched by default + count($records[0]); - .. code-block:: java + .. code-tab:: java - final List ids = asList((Object[])models.execute( - "execute_kw", asList( - db, uid, password, - "res.partner", "search", - asList(asList( - asList("is_company", "=", true))), - new HashMap() {{ put("limit", 1); }}))); - final Map record = (Map)((Object[])models.execute( - "execute_kw", asList( - db, uid, password, - "res.partner", "read", - asList(ids) - ) - ))[0]; - // count the number of fields fetched by default - record.size(); + final List ids = asList((Object[])models.execute( + "execute_kw", asList( + db, uid, password, + "res.partner", "search", + asList(asList( + asList("is_company", "=", true))), + new HashMap() {{ put("limit", 1); }}))); + final Map record = (Map)((Object[])models.execute( + "execute_kw", asList( + db, uid, password, + "res.partner", "read", + asList(ids) + ) + ))[0]; + // count the number of fields fetched by default + record.size(); - .. code-block:: json + Result: - 121 + .. code-block:: json -Conversedly, picking only three fields deemed interesting. + 121 -.. container:: doc-aside + Conversely, picking only three fields deemed interesting. - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - models.execute_kw(db, uid, password, - 'res.partner', 'read', - [ids], {'fields': ['name', 'country_id', 'comment']}) + models.execute_kw(db, uid, password, 'res.partner', 'read', [ids], {'fields': ['name', 'country_id', 'comment']}) - .. code-block:: ruby + .. code-tab:: ruby - models.execute_kw(db, uid, password, - 'res.partner', 'read', - [ids], {fields: %w(name country_id comment)}) + models.execute_kw(db, uid, password, 'res.partner', 'read', [ids], {fields: %w(name country_id comment)}) - .. code-block:: php + .. code-tab:: php - $models->execute_kw($db, $uid, $password, - 'res.partner', 'read', - array($ids), - array('fields'=>array('name', 'country_id', 'comment'))); + $models->execute_kw($db, $uid, $password, 'res.partner', 'read', array($ids), array('fields'=>array('name', 'country_id', 'comment'))); - .. code-block:: java + .. code-tab:: java - asList((Object[])models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "read", - asList(ids), - new HashMap() {{ - put("fields", asList("name", "country_id", "comment")); - }} - ))); + asList((Object[])models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "read", + asList(ids), + new HashMap() {{ + put("fields", asList("name", "country_id", "comment")); + }} + ))); - .. code-block:: json + Result: - [{"comment": false, "country_id": [21, "Belgium"], "id": 7, "name": "Agrolait"}] + .. code-block:: json -.. note:: even if the ``id`` field is not requested, it is always returned + [{"comment": false, "country_id": [21, "Belgium"], "id": 7, "name": "Agrolait"}] -Listing record fields ---------------------- +.. note:: + Even if the ``id`` field is not requested, it is always returned. + +List record fields +------------------ :meth:`~odoo.models.Model.fields_get` can be used to inspect a model's fields and check which ones seem to be of interest. @@ -661,283 +530,263 @@ Because it returns a large amount of meta-information (it is also used by client programs) it should be filtered before printing, the most interesting items for a human user are ``string`` (the field's label), ``help`` (a help text if available) and ``type`` (to know which values to expect, or to send when -updating a record): +updating a record). -.. container:: doc-aside +.. example:: - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - models.execute_kw( - db, uid, password, 'res.partner', 'fields_get', - [], {'attributes': ['string', 'help', 'type']}) + models.execute_kw(db, uid, password, 'res.partner', 'fields_get', [], {'attributes': ['string', 'help', 'type']}) - .. code-block:: ruby + .. code-tab:: ruby - models.execute_kw( - db, uid, password, 'res.partner', 'fields_get', - [], {attributes: %w(string help type)}) + models.execute_kw(db, uid, password, 'res.partner', 'fields_get', [], {attributes: %w(string help type)}) - .. code-block:: php + .. code-tab:: php - $models->execute_kw($db, $uid, $password, - 'res.partner', 'fields_get', - array(), array('attributes' => array('string', 'help', 'type'))); + $models->execute_kw($db, $uid, $password, 'res.partner', 'fields_get', array(), array('attributes' => array('string', 'help', 'type'))); - .. code-block:: java + .. code-tab:: java - (Map>)models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "fields_get", - emptyList(), - new HashMap() {{ - put("attributes", asList("string", "help", "type")); - }} - )); + (Map>)models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "fields_get", + emptyList(), + new HashMap() {{ + put("attributes", asList("string", "help", "type")); + }} + )); - .. code-block:: json + Result: - { - "ean13": { - "type": "char", - "help": "BarCode", - "string": "EAN13" - }, - "property_account_position_id": { - "type": "many2one", - "help": "The fiscal position will determine taxes and accounts used for the partner.", - "string": "Fiscal Position" - }, - "signup_valid": { - "type": "boolean", - "help": "", - "string": "Signup Token is Valid" - }, - "date_localization": { - "type": "date", - "help": "", - "string": "Geo Localization Date" - }, - "ref_company_ids": { - "type": "one2many", - "help": "", - "string": "Companies that refers to partner" - }, - "sale_order_count": { - "type": "integer", - "help": "", - "string": "# of Sales Order" - }, - "purchase_order_count": { - "type": "integer", - "help": "", - "string": "# of Purchase Order" - }, + .. code-block:: json + + { + "ean13": { + "type": "char", + "help": "BarCode", + "string": "EAN13" + }, + "property_account_position_id": { + "type": "many2one", + "help": "The fiscal position will determine taxes and accounts used for the partner.", + "string": "Fiscal Position" + }, + "signup_valid": { + "type": "boolean", + "help": "", + "string": "Signup Token is Valid" + }, + "date_localization": { + "type": "date", + "help": "", + "string": "Geo Localization Date" + }, + "ref_company_ids": { + "type": "one2many", + "help": "", + "string": "Companies that refers to partner" + }, + "sale_order_count": { + "type": "integer", + "help": "", + "string": "# of Sales Order" + }, + "purchase_order_count": { + "type": "integer", + "help": "", + "string": "# of Purchase Order" + }, Search and read --------------- Because it is a very common task, Odoo provides a -:meth:`~odoo.models.Model.search_read` shortcut which as its name suggests is +:meth:`~odoo.models.Model.search_read` shortcut which, as its name suggests, is equivalent to a :meth:`~odoo.models.Model.search` followed by a :meth:`~odoo.models.Model.read`, but avoids having to perform two requests and keep ids around. Its arguments are similar to :meth:`~odoo.models.Model.search`'s, but it can also take a list of ``fields`` (like :meth:`~odoo.models.Model.read`, -if that list is not provided it will fetch all fields of matched records): +if that list is not provided it will fetch all fields of matched records). -.. container:: doc-aside +.. example:: - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - models.execute_kw(db, uid, password, - 'res.partner', 'search_read', - [[['is_company', '=', True]]], - {'fields': ['name', 'country_id', 'comment'], 'limit': 5}) + models.execute_kw(db, uid, password, 'res.partner', 'search_read', [[['is_company', '=', True]]], {'fields': ['name', 'country_id', 'comment'], 'limit': 5}) - .. code-block:: ruby + .. code-tab:: ruby - models.execute_kw(db, uid, password, - 'res.partner', 'search_read', - [[['is_company', '=', true]]], - {fields: %w(name country_id comment), limit: 5}) + models.execute_kw(db, uid, password, 'res.partner', 'search_read', [[['is_company', '=', true]]], {fields: %w(name country_id comment), limit: 5}) - .. code-block:: php + .. code-tab:: php - $models->execute_kw($db, $uid, $password, - 'res.partner', 'search_read', - array(array(array('is_company', '=', true))), - array('fields'=>array('name', 'country_id', 'comment'), 'limit'=>5)); + $models->execute_kw($db, $uid, $password, 'res.partner', 'search_read', array(array(array('is_company', '=', true))), array('fields'=>array('name', 'country_id', 'comment'), 'limit'=>5)); - .. code-block:: java + .. code-tab:: java - asList((Object[])models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "search_read", - asList(asList( - asList("is_company", "=", true))), - new HashMap() {{ - put("fields", asList("name", "country_id", "comment")); - put("limit", 5); - }} - ))); + asList((Object[])models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "search_read", + asList(asList( + asList("is_company", "=", true))), + new HashMap() {{ + put("fields", asList("name", "country_id", "comment")); + put("limit", 5); + }} + ))); - .. code-block:: json + Result: - [ - { - "comment": false, - "country_id": [ 21, "Belgium" ], - "id": 7, - "name": "Agrolait" - }, - { - "comment": false, - "country_id": [ 76, "France" ], - "id": 18, - "name": "Axelor" - }, - { - "comment": false, - "country_id": [ 233, "United Kingdom" ], - "id": 12, - "name": "Bank Wealthy and sons" - }, - { - "comment": false, - "country_id": [ 105, "India" ], - "id": 14, - "name": "Best Designers" - }, - { - "comment": false, - "country_id": [ 76, "France" ], - "id": 17, - "name": "Camptocamp" - } - ] + .. code-block:: json + [ + { + "comment": false, + "country_id": [ 21, "Belgium" ], + "id": 7, + "name": "Agrolait" + }, + { + "comment": false, + "country_id": [ 76, "France" ], + "id": 18, + "name": "Axelor" + }, + { + "comment": false, + "country_id": [ 233, "United Kingdom" ], + "id": 12, + "name": "Bank Wealthy and sons" + }, + { + "comment": false, + "country_id": [ 105, "India" ], + "id": 14, + "name": "Best Designers" + }, + { + "comment": false, + "country_id": [ 76, "France" ], + "id": 17, + "name": "Camptocamp" + } + ] Create records -------------- Records of a model are created using :meth:`~odoo.models.Model.create`. The -method will create a single record and return its database identifier. +method creates a single record and returns its database identifier. :meth:`~odoo.models.Model.create` takes a mapping of fields to values, used to initialize the record. For any field which has a default value and is not set through the mapping argument, the default value will be used. -.. container:: doc-aside +.. example:: - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{ - 'name': "New Partner", - }]) + id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{'name': "New Partner"}]) - .. code-block:: ruby + .. code-tab:: ruby - id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{ - name: "New Partner", - }]) + id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{name: "New Partner"}]) - .. code-block:: php + .. code-tab:: php - $id = $models->execute_kw($db, $uid, $password, - 'res.partner', 'create', - array(array('name'=>"New Partner"))); + $id = $models->execute_kw($db, $uid, $password, 'res.partner', 'create', array(array('name'=>"New Partner"))); - .. code-block:: java + .. code-tab:: java - final Integer id = (Integer)models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "create", - asList(new HashMap() {{ put("name", "New Partner"); }}) - )); + final Integer id = (Integer)models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "create", + asList(new HashMap() {{ put("name", "New Partner"); }}) + )); - .. code-block:: json + Result: - 78 + .. code-block:: json + + 78 .. warning:: + While most value types are what would expect (integer for + :class:`~odoo.fields.Integer`, string for :class:`~odoo.fields.Char` + or :class:`~odoo.fields.Text`), - while most value types are what would be expected (integer for - :class:`~odoo.fields.Integer`, string for :class:`~odoo.fields.Char` - or :class:`~odoo.fields.Text`), - - * :class:`~odoo.fields.Date`, :class:`~odoo.fields.Datetime` and - :class:`~odoo.fields.Binary` fields use string values - * :class:`~odoo.fields.One2many` and :class:`~odoo.fields.Many2many` - use a special command protocol detailed in :meth:`the documentation to - the write method `. + - :class:`~odoo.fields.Date`, :class:`~odoo.fields.Datetime` and + :class:`~odoo.fields.Binary` fields use string values + - :class:`~odoo.fields.One2many` and :class:`~odoo.fields.Many2many` + use a special command protocol detailed in :meth:`the documentation to + the write method `. Update records -------------- -Records can be updated using :meth:`~odoo.models.Model.write`, it takes +Records can be updated using :meth:`~odoo.models.Model.write`. It takes a list of records to update and a mapping of updated fields to values similar to :meth:`~odoo.models.Model.create`. Multiple records can be updated simultaneously, but they will all get the same -values for the fields being set. It is not currently possible to perform +values for the fields being set. It is not possible to perform "computed" updates (where the value being set depends on an existing value of a record). -.. container:: doc-aside +.. example:: - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - models.execute_kw(db, uid, password, 'res.partner', 'write', [[id], { - 'name': "Newer partner" - }]) - # get record name after having changed it - models.execute_kw(db, uid, password, 'res.partner', 'name_get', [[id]]) + models.execute_kw(db, uid, password, 'res.partner', 'write', [[id], {'name': "Newer partner"}]) + # get record name after having changed it + models.execute_kw(db, uid, password, 'res.partner', 'name_get', [[id]]) - .. code-block:: ruby + .. code-tab:: ruby - models.execute_kw(db, uid, password, 'res.partner', 'write', [[id], { - name: "Newer partner" - }]) - # get record name after having changed it - models.execute_kw(db, uid, password, 'res.partner', 'name_get', [[id]]) + models.execute_kw(db, uid, password, 'res.partner', 'write', [[id], {name: "Newer partner"}]) + # get record name after having changed it + models.execute_kw(db, uid, password, 'res.partner', 'name_get', [[id]]) - .. code-block:: php + .. code-tab:: php - $models->execute_kw($db, $uid, $password, 'res.partner', 'write', - array(array($id), array('name'=>"Newer partner"))); - // get record name after having changed it - $models->execute_kw($db, $uid, $password, - 'res.partner', 'name_get', array(array($id))); + $models->execute_kw($db, $uid, $password, 'res.partner', 'write', array(array($id), array('name'=>"Newer partner"))); + // get record name after having changed it + $models->execute_kw($db, $uid, $password, + 'res.partner', 'name_get', array(array($id))); - .. code-block:: java + .. code-tab:: java - models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "write", - asList( - asList(id), - new HashMap() {{ put("name", "Newer Partner"); }} - ) - )); - // get record name after having changed it - asList((Object[])models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "name_get", - asList(asList(id)) - ))); + models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "write", + asList( + asList(id), + new HashMap() {{ put("name", "Newer Partner"); }} + ) + )); + // get record name after having changed it + asList((Object[])models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "name_get", + asList(asList(id)) + ))); - .. code-block:: json + Result: - [[78, "Newer partner"]] + .. code-block:: json + + [[78, "Newer partner"]] Delete records -------------- @@ -945,59 +794,52 @@ Delete records Records can be deleted in bulk by providing their ids to :meth:`~odoo.models.Model.unlink`. -.. container:: doc-aside +.. example:: - .. switcher:: + .. tabs:: - .. code-block:: python3 + .. code-tab:: python - models.execute_kw(db, uid, password, 'res.partner', 'unlink', [[id]]) - # check if the deleted record is still in the database - models.execute_kw(db, uid, password, - 'res.partner', 'search', [[['id', '=', id]]]) + models.execute_kw(db, uid, password, 'res.partner', 'unlink', [[id]]) + # check if the deleted record is still in the database + models.execute_kw(db, uid, password, 'res.partner', 'search', [[['id', '=', id]]]) - .. code-block:: ruby + .. code-tab:: ruby - models.execute_kw(db, uid, password, 'res.partner', 'unlink', [[id]]) - # check if the deleted record is still in the database - models.execute_kw(db, uid, password, - 'res.partner', 'search', [[['id', '=', id]]]) + models.execute_kw(db, uid, password, 'res.partner', 'unlink', [[id]]) + # check if the deleted record is still in the database + models.execute_kw(db, uid, password, 'res.partner', 'search', [[['id', '=', id]]]) - .. code-block:: php + .. code-tab:: php - $models->execute_kw($db, $uid, $password, - 'res.partner', 'unlink', - array(array($id))); - // check if the deleted record is still in the database - $models->execute_kw($db, $uid, $password, - 'res.partner', 'search', - array(array(array('id', '=', $id)))); + $models->execute_kw($db, $uid, $password, 'res.partner', 'unlink', array(array($id))); + // check if the deleted record is still in the database + $models->execute_kw( + $db, $uid, $password, 'res.partner', 'search', array(array(array('id', '=', $id))) + ); - .. code-block:: java + .. code-tab:: java - models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "unlink", - asList(asList(id)))); - // check if the deleted record is still in the database - asList((Object[])models.execute("execute_kw", asList( - db, uid, password, - "res.partner", "search", - asList(asList(asList("id", "=", 78))) - ))); + models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "unlink", + asList(asList(id)))); + // check if the deleted record is still in the database + asList((Object[])models.execute("execute_kw", asList( + db, uid, password, + "res.partner", "search", + asList(asList(asList("id", "=", 78))) + ))); - .. code-block:: json + Result: - [] + .. code-block:: json + + [] Inspection and introspection ---------------------------- -.. todo:: ``get_external_id`` is kinda crap and may not return an id: it just - gets a random existing xid but won't generate one if there is no - xid currently associated with the record. And operating with xids - isn't exactly fun in RPC. - While we previously used :meth:`~odoo.models.Model.fields_get` to query a model and have been using an arbitrary model from the start, Odoo stores most model metadata inside a few meta-models which allow both querying the @@ -1007,9 +849,9 @@ XML-RPC. .. _reference/webservice/inspection/models: ``ir.model`` -'''''''''''' +~~~~~~~~~~~~ -Provides information about Odoo models via its various fields +Provides information about Odoo models via its various fields. ``name`` a human-readable description of the model @@ -1030,132 +872,119 @@ Provides information about Odoo models via its various fields ``ir.model`` can be used to -* query the system for installed models (as a precondition to operations - on the model or to explore the system's content) -* get information about a specific model (generally by listing the fields - associated with it) -* create new models dynamically over RPC +- Query the system for installed models (as a precondition to operations + on the model or to explore the system's content). +- Get information about a specific model (generally by listing the fields + associated with it). +- Create new models dynamically over RPC. -.. warning:: +.. important:: + * Custom model names must start with ``x_``. + * The ``state`` must be provided and set to ``manual``, otherwise the model will + not be loaded. + * It is not possible to add new *methods* to a custom model, only fields. - * "custom" model names must start with ``x_`` - * the ``state`` must be provided and ``manual``, otherwise the model will - not be loaded - * it is not possible to add new *methods* to a custom model, only fields +.. example:: -.. container:: doc-aside + A custom model will initially contain only the "built-in" fields available + on all models: - a custom model will initially contain only the "built-in" fields available - on all models: + .. tabs:: - .. switcher:: + .. code-tab:: python - .. code-block:: python3 + models.execute_kw(db, uid, password, 'ir.model', 'create', [{ + 'name': "Custom Model", + 'model': "x_custom_model", + 'state': 'manual', + }]) + models.execute_kw(db, uid, password, 'x_custom_model', 'fields_get', [], {'attributes': ['string', 'help', 'type']}) - models.execute_kw(db, uid, password, 'ir.model', 'create', [{ - 'name': "Custom Model", - 'model': "x_custom_model", - 'state': 'manual', - }]) - models.execute_kw( - db, uid, password, 'x_custom_model', 'fields_get', - [], {'attributes': ['string', 'help', 'type']}) + .. code-tab:: php - .. code-block:: php + $models->execute_kw($db, $uid, $password, 'ir.model', 'create', array(array( + 'name' => "Custom Model", + 'model' => 'x_custom_model', + 'state' => 'manual' + ))); + $models->execute_kw($db, $uid, $password, 'x_custom_model', 'fields_get', array(), array('attributes' => array('string', 'help', 'type'))); - $models->execute_kw( - $db, $uid, $password, - 'ir.model', 'create', array(array( - 'name' => "Custom Model", - 'model' => 'x_custom_model', - 'state' => 'manual' - )) - ); - $models->execute_kw( - $db, $uid, $password, - 'x_custom_model', 'fields_get', - array(), - array('attributes' => array('string', 'help', 'type')) - ); + .. code-tab:: ruby - .. code-block:: ruby + models.execute_kw(db, uid, password, 'ir.model', 'create', [{ + name: "Custom Model", + model: 'x_custom_model', + state: 'manual' + }]) + fields = models.execute_kw(db, uid, password, 'x_custom_model', 'fields_get', [], {attributes: %w(string help type)}) - models.execute_kw( - db, uid, password, - 'ir.model', 'create', [{ - name: "Custom Model", - model: 'x_custom_model', - state: 'manual' - }]) - fields = models.execute_kw( - db, uid, password, 'x_custom_model', 'fields_get', - [], {attributes: %w(string help type)}) + .. code-tab:: java - .. code-block:: java + models.execute( + "execute_kw", asList( + db, uid, password, + "ir.model", "create", + asList(new HashMap() {{ + put("name", "Custom Model"); + put("model", "x_custom_model"); + put("state", "manual"); + }}) + )); + final Object fields = models.execute( + "execute_kw", asList( + db, uid, password, + "x_custom_model", "fields_get", + emptyList(), + new HashMap () {{ + put("attributes", asList( + "string", + "help", + "type")); + }} + )); - models.execute( - "execute_kw", asList( - db, uid, password, - "ir.model", "create", - asList(new HashMap() {{ - put("name", "Custom Model"); - put("model", "x_custom_model"); - put("state", "manual"); - }}) - )); - final Object fields = models.execute( - "execute_kw", asList( - db, uid, password, - "x_custom_model", "fields_get", - emptyList(), - new HashMap () {{ - put("attributes", asList( - "string", - "help", - "type")); - }} - )); + Result: - .. code-block:: json + .. code-block:: json - { - "create_uid": { - "type": "many2one", - "string": "Created by" - }, - "create_date": { - "type": "datetime", - "string": "Created on" - }, - "__last_update": { - "type": "datetime", - "string": "Last Modified on" - }, - "write_uid": { - "type": "many2one", - "string": "Last Updated by" - }, - "write_date": { - "type": "datetime", - "string": "Last Updated on" - }, - "display_name": { - "type": "char", - "string": "Display Name" - }, - "id": { - "type": "integer", - "string": "Id" - } - } + { + "create_uid": { + "type": "many2one", + "string": "Created by" + }, + "create_date": { + "type": "datetime", + "string": "Created on" + }, + "__last_update": { + "type": "datetime", + "string": "Last Modified on" + }, + "write_uid": { + "type": "many2one", + "string": "Last Updated by" + }, + "write_date": { + "type": "datetime", + "string": "Last Updated on" + }, + "display_name": { + "type": "char", + "string": "Display Name" + }, + "id": { + "type": "integer", + "string": "Id" + } + } .. _reference/webservice/inspection/fields: ``ir.model.fields`` -''''''''''''''''''' +~~~~~~~~~~~~~~~~~~~ Provides information about the fields of Odoo models and allows adding -custom fields without using Python code +custom fields without using Python code. ``model_id`` :class:`~odoo.fields.Many2one` to @@ -1178,155 +1007,123 @@ custom fields without using Python code type-specific properties and customizations, see :ref:`the fields documentation ` for details -Like custom models, only new fields created with ``state="manual"`` are -activated as actual fields on the model. +.. important:: + - Like custom models, only new fields created with ``state="manual"`` are activated as actual + fields on the model. + - Computed fields can not be added via ``ir.model.fields``, some field meta-information + (defaults, onchange) can not be set either. -.. warning:: computed fields can not be added via ``ir.model.fields``, some - field meta-information (defaults, onchange) can not be set either +.. example:: -.. todo:: maybe new-API fields could store constant ``default`` in a new - column, maybe JSON-encoded? + .. tabs:: -.. container:: doc-aside + .. code-tab:: python - .. switcher:: + id = models.execute_kw(db, uid, password, 'ir.model', 'create', [{ + 'name': "Custom Model", + 'model': "x_custom", + 'state': 'manual', + }]) + models.execute_kw(db, uid, password, 'ir.model.fields', 'create', [{ + 'model_id': id, + 'name': 'x_name', + 'ttype': 'char', + 'state': 'manual', + 'required': True, + }]) + record_id = models.execute_kw(db, uid, password, 'x_custom', 'create', [{'x_name': "test record"}]) + models.execute_kw(db, uid, password, 'x_custom', 'read', [[record_id]]) - .. code-block:: python3 + .. code-tab:: php - id = models.execute_kw(db, uid, password, 'ir.model', 'create', [{ - 'name': "Custom Model", - 'model': "x_custom", - 'state': 'manual', - }]) - models.execute_kw( - db, uid, password, - 'ir.model.fields', 'create', [{ - 'model_id': id, - 'name': 'x_name', - 'ttype': 'char', - 'state': 'manual', - 'required': True, - }]) - record_id = models.execute_kw( - db, uid, password, - 'x_custom', 'create', [{ - 'x_name': "test record", - }]) - models.execute_kw(db, uid, password, 'x_custom', 'read', [[record_id]]) + $id = $models->execute_kw($db, $uid, $password, 'ir.model', 'create', array(array( + 'name' => "Custom Model", + 'model' => 'x_custom', + 'state' => 'manual' + ))); + $models->execute_kw($db, $uid, $password, 'ir.model.fields', 'create', array(array( + 'model_id' => $id, + 'name' => 'x_name', + 'ttype' => 'char', + 'state' => 'manual', + 'required' => true + ))); + $record_id = $models->execute_kw($db, $uid, $password, 'x_custom', 'create', array(array('x_name' => "test record"))); + $models->execute_kw($db, $uid, $password, 'x_custom', 'read', array(array($record_id))); - .. code-block:: php + .. code-tab:: ruby - $id = $models->execute_kw( - $db, $uid, $password, - 'ir.model', 'create', array(array( - 'name' => "Custom Model", - 'model' => 'x_custom', - 'state' => 'manual' - )) - ); - $models->execute_kw( - $db, $uid, $password, - 'ir.model.fields', 'create', array(array( - 'model_id' => $id, - 'name' => 'x_name', - 'ttype' => 'char', - 'state' => 'manual', - 'required' => true - )) - ); - $record_id = $models->execute_kw( - $db, $uid, $password, - 'x_custom', 'create', array(array( - 'x_name' => "test record" - )) - ); - $models->execute_kw( - $db, $uid, $password, - 'x_custom', 'read', - array(array($record_id))); + id = models.execute_kw(db, uid, password, 'ir.model', 'create', [{ + name: "Custom Model", + model: "x_custom", + state: 'manual' + }]) + models.execute_kw(db, uid, password, 'ir.model.fields', 'create', [{ + model_id: id, + name: "x_name", + ttype: "char", + state: "manual", + required: true + }]) + record_id = models.execute_kw(db, uid, password, 'x_custom', 'create', [{x_name: "test record"}]) + models.execute_kw(db, uid, password, 'x_custom', 'read', [[record_id]]) - .. code-block:: ruby + .. code-tab:: java - id = models.execute_kw( - db, uid, password, - 'ir.model', 'create', [{ - name: "Custom Model", - model: "x_custom", - state: 'manual' - }]) - models.execute_kw( - db, uid, password, - 'ir.model.fields', 'create', [{ - model_id: id, - name: "x_name", - ttype: "char", - state: "manual", - required: true - }]) - record_id = models.execute_kw( - db, uid, password, - 'x_custom', 'create', [{ - x_name: "test record" - }]) - models.execute_kw( - db, uid, password, - 'x_custom', 'read', [[record_id]]) + final Integer id = (Integer)models.execute( + "execute_kw", asList( + db, uid, password, + "ir.model", "create", + asList(new HashMap() {{ + put("name", "Custom Model"); + put("model", "x_custom"); + put("state", "manual"); + }}) + )); + models.execute( + "execute_kw", asList( + db, uid, password, + "ir.model.fields", "create", + asList(new HashMap() {{ + put("model_id", id); + put("name", "x_name"); + put("ttype", "char"); + put("state", "manual"); + put("required", true); + }}) + )); + final Integer record_id = (Integer)models.execute( + "execute_kw", asList( + db, uid, password, + "x_custom", "create", + asList(new HashMap() {{ + put("x_name", "test record"); + }}) + )); - .. code-block:: java + client.execute( + "execute_kw", asList( + db, uid, password, + "x_custom", "read", + asList(asList(record_id)) + )); - final Integer id = (Integer)models.execute( - "execute_kw", asList( - db, uid, password, - "ir.model", "create", - asList(new HashMap() {{ - put("name", "Custom Model"); - put("model", "x_custom"); - put("state", "manual"); - }}) - )); - models.execute( - "execute_kw", asList( - db, uid, password, - "ir.model.fields", "create", - asList(new HashMap() {{ - put("model_id", id); - put("name", "x_name"); - put("ttype", "char"); - put("state", "manual"); - put("required", true); - }}) - )); - final Integer record_id = (Integer)models.execute( - "execute_kw", asList( - db, uid, password, - "x_custom", "create", - asList(new HashMap() {{ - put("x_name", "test record"); - }}) - )); + Result: - client.execute( - "execute_kw", asList( - db, uid, password, - "x_custom", "read", - asList(asList(record_id)) - )); - - .. code-block:: json - - [ - { - "create_uid": [1, "Administrator"], - "x_name": "test record", - "__last_update": "2014-11-12 16:32:13", - "write_uid": [1, "Administrator"], - "write_date": "2014-11-12 16:32:13", - "create_date": "2014-11-12 16:32:13", - "id": 1, - "display_name": "test record" - } - ] + .. code-block:: json + [ + { + "create_uid": [1, "Administrator"], + "x_name": "test record", + "__last_update": "2014-11-12 16:32:13", + "write_uid": [1, "Administrator"], + "write_date": "2014-11-12 16:32:13", + "create_date": "2014-11-12 16:32:13", + "id": 1, + "display_name": "test record" + } + ] .. _PostgreSQL: https://www.postgresql.org .. _XML-RPC: https://en.wikipedia.org/wiki/XML-RPC diff --git a/content/developer/reference/backend/security.rst b/content/developer/reference/backend/security.rst index 38d634bce..30c2ad1c5 100644 --- a/content/developer/reference/backend/security.rst +++ b/content/developer/reference/backend/security.rst @@ -203,7 +203,7 @@ Unsafe Public Methods --------------------- Any public method can be executed via a :ref:`RPC call -` with the chosen parameters. The methods +` with the chosen parameters. The methods starting with a ``_`` are not callable from an action button or external API. On public methods, the record on which a method is executed and the parameters