Стандартным механизмом для расширения функционала Odoo является использование модулей, но многие его функции и все данные доступны извне для анализа или интеграции с различными инструментами. Часть API Модели доступна через XML-RPC и может быть задействована на разных языках программирования.
Соединение
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))
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
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");
final XmlRpcClient client = new XmlRpcClient();
final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl();
start_config.setServerURL(new URL("https://demo.odoo.com/start"));
final Map<String, String> info = (Map<String, String>)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)));
}});
}};
Настройка
Если у вас уже есть установленные сервер Odoo, то вы может использовать следующие параметры
Предупреждение
Для экземпляров Odoo Online (<домен> .odoo.com) пользователи создаются без локального пароля (вы авторизуетесь как пользователь, вошедший в систему через систему аутентификации Odoo Online, а не на самом сервере). Чтобы использовать XML-RPC на экземплярах Odoo Online, вам необходимо установить пароль для учетной записи пользователя, которую вы хотите использовать:
- Зайдите как администратор
- Перейдите
- Кликните на пользователя, которому хотите предоставить доступ с помощью XML-RPC
- Кликните по кнопке Изменить пароль
- Введите в поле Новый пароль собственно сам пароль а затем нажмине Изменить пароль.
Параметр url будет таким же как ссылка к вашему экземпляру Odoo Online (например https://mycompany.odoo.com), параметр database name это имя экземпляра (например mycompany). Парметр username это логин пользователя, для которого вы меняли пароль.
- Python 2
- Ruby
- PHP
- Java
url = <insert server URL>
db = <insert database name>
username = 'admin'
password = <insert password for your admin user (default: admin)>
url = <insert server URL>
db = <insert database name>
username = "admin"
password = <insert password for your admin user (default: admin)>
$url = <insert server URL>;
$db = <insert database name>;
$username = "admin";
$password = <insert password for your admin user (default: admin)>;
final String url = <insert server URL>,
db = <insert database name>,
username = "admin",
password = <insert password for your admin user (default: admin)>;
Демо
Чтобы упростить себе жизнь, вы также можете запросить тестовую базу данных по этой ссылке https://demo.odoo.com:
- Python 2
- Ruby
- PHP
- Java
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']
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_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']);
Примечание
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.
Since calls are performed over HTTPS, it also requires that the OpenSSL extension be enabled.
final XmlRpcClient client = new XmlRpcClient();
final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl();
start_config.setServerURL(new URL("https://demo.odoo.com/start"));
final Map<String, String> info = (Map<String, String>)client.execute(
start_config, "start", emptyList());
final String url = info.get("host"),
db = info.get("database"),
username = info.get("user"),
password = info.get("password");
Авторизация
Odoo требует чтобы пользователи API проходили авторизацию прежде чем они смогут делать запросы.
Эндпоинт xmlrpc/2/common
предоставляет доступ к вызовам, которые не требуют аутентификации, например сама аутентификация или запрос информации о версии. Самый простой способ проверить правильность информации о соединении перед аутентификацией - запросить версию сервера. Сама аутентификация выполняется через функцию``authenticate`` и возвращает идентификатор пользователя (uid
) используемый в дальнейшем вместо логина.
- Python 2
- Ruby
- PHP
- Java
common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
common.version()
common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common")
common.call('version')
$common = ripcord::client("$url/xmlrpc/2/common");
$common->version();
final XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl();
common_config.setServerURL(
new URL(String.format("%s/xmlrpc/2/common", url)));
client.execute(common_config, "version", emptyList());
{
"server_version": "13.0",
"server_version_info": [13, 0, 0, "final", 0],
"server_serie": "13.0",
"protocol_version": 1,
}
- Python 2
- Ruby
- PHP
- Java
uid = common.authenticate(db, username, password, {})
uid = common.call('authenticate', db, username, password, {})
$uid = $common->authenticate($db, $username, $password, array());
int uid = (int)client.execute(
common_config, "authenticate", asList(
db, username, password, emptyMap()));
Методы
Вторым эндпоинтом является xmlrpc/2/object
, он используется для вызова методов моделей с помощью функции удаленного вызова процедур(RPC) execute_kw
.
Каждый вызов execute_kw
принимает следующие параметры:
- имя базы данных - string
- идентификатор пользователя (полученный с помощью функции
authenticate
) - integer - пароль пользователя - строка
- имя модели - строка
- имя вызываемого метода внутри модели - строка
- список позиционных параметров - массив/список
- ключевые параметры - словарь
Например, если мы имеет доступ для чтения к модели res.partner
мы можем вызвать метод check_access_rights
с позиционным аргументом operation
и ключевым аргуметом raise_exception
(чтобы получить результат true/false , а не true/error):
- Python 2
- Ruby
- PHP
- Java
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.new2("#{url}/xmlrpc/2/object").proxy
models.execute_kw(db, uid, password,
'res.partner', 'check_access_rights',
['read'], {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));
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); }}
));
true
Список записей
Записи могут быть перечислены и отфильтрованы с помощью search()
.
search()
принимает обязательный параметр:ref:[UNKNOWN NODE title_reference] (возможно пустой) и возвращает id базы данных всех записей, соответствующих фильтру. Например перечислить клиентов, который являются компаниями,:
- Python 2
- Ruby
- PHP
- Java
models.execute_kw(db, uid, password,
'res.partner', 'search',
[[['is_company', '=', True]]])
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))));
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]
Разбиение на страницы
По умолчанию поиск вернет идентификаторы всех записей, соответствующих условию, которое может быть очень велико. Параметры offset
и limit
позволяют возвращать подмножества всех записей, удовлетворяющих запросу.
- Python 2
- Ruby
- PHP
- Java
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})
$models->execute_kw($db, $uid, $password,
'res.partner', 'search',
array(array(array('is_company', '=', true))),
array('offset'=>10, '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); }}
)));
[13, 20, 30, 22, 29]
Количество записей
Вместо того, чтобы запросить гигантский список записей, а затем посчитать их, search_count()
запрос может быть использован для получения только количества записей удовлетворяющих условию. Он использует такой же domain фильтр, как и search()
и никаких других параметров.
- Python 2
- Ruby
- PHP
- Java
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]]])
$models->execute_kw($db, $uid, $password,
'res.partner', 'search_count',
array(array(array('is_company', '=', true))));
(Integer)models.execute("execute_kw", asList(
db, uid, password,
"res.partner", "search_count",
asList(asList(
asList("is_company", "=", true)))
));
19
Предупреждение
Запрос search
, а затем search_count
(или в обратном порядке) может не выдать согласованного результата, если другие пользователи используют сервер: сохраненные данные могли быть изменены между запросами
Чтение записей
Доступ к данным записи осуществляется с помощью метода read()
, который содержит список идентификаторов (которые были возвращены по запросу: search()
) и опционально список полей, данные из которых мы хотим получить. По умолчанию вы получите значение всех полей, к которым имеет доступ текущий пользователь, количество которых может быть очень большим.
- Python 2
- Ruby
- PHP
- Java
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]).first
# count the number of fields fetched by default
record.length
$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]);
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();
121
В случае, если нам интересны только три поля.
- Python 2
- Ruby
- PHP
- Java
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: %w(name country_id comment)})
$models->execute_kw($db, $uid, $password,
'res.partner', 'read',
array($ids),
array('fields'=>array('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"));
}}
)));
[{"comment": false, "country_id": [21, "Belgium"], "id": 7, "name": "Agrolait"}]
Примечание
Даже если id
поля не был запрошен, его значение всегда будет содержаться в ответе
Список полей записи
fields_get()
может быть использован для для проверки полей модели на наличие интересующей вас информации.
Поскольку данный запрос возвращает большое количество мета-информации (он так же используется программами-клиентами), она должна быть отфильтрована перед печатью, наиболее интересные элементы для человеческого восприятия это string
(описание поля), help
(справочный текст, если имеется) и type
(чтобы знать какое значение ожидать или посылать при обновлении записи):
- Python 2
- Ruby
- PHP
- Java
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: %w(string help type)})
$models->execute_kw($db, $uid, $password,
'res.partner', 'fields_get',
array(), array('attributes' => array('string', 'help', 'type')));
(Map<String, Map<String, Object>>)models.execute("execute_kw", asList(
db, uid, password,
"res.partner", "fields_get",
emptyList(),
new HashMap() {{
put("attributes", asList("string", "help", "type"));
}}
));
{
"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"
},
Поиск и чтение
В связи с тем, что это частая задача, Odoo предоставляет search_read()
запрос, который согласно его наименованию search()
следует за read()
, но вместо двух запросов позволяет сделать один и сохранить идентификаторы.
Его аргументы такие же как и у search()
“s, но он так же понимает список fields
(как read()
, если в этом списке нет критериев выбора, он вернет все поля совпадающих с условиями поиска записей):
- Python 2
- Ruby
- PHP
- Java
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: %w(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));
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);
}}
)));
[
{
"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()
. Метод создаст одну запись и вернет ее id.
create()
принимает словарь где ключ это имя поля, а значение - сохраняемые туда данные использует их для инициализации записи. Для каждого поля, для которого не указаны пара имя-значение, будет присвоено значение по умолчанию.
- Python 2
- Ruby
- PHP
- Java
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",
}])
$id = $models->execute_kw($db, $uid, $password,
'res.partner', 'create',
array(array('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"); }})
));
78
Обновление записей
Значение записей могут быть обновлены используя метод write()
, он принимает список записей и словарь обновлямых полей и их значений точно так же как и метод create()
.
Несколько записей могут обновляться одновременно, но все они получат одинаковые значения для всех указанных полей. В настоящее время невозможно выполнить «вычисляемые» обновления (когда устанавливаемое значение зависит от существующего значения записи).
- Python 2
- Ruby
- PHP
- Java
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]])
$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("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))
)));
[[78, "Newer partner"]]
Удаление записей
Записи могут быть удалены массово, путем указания их id unlink()
.
- Python 2
- Ruby
- PHP
- Java
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]]])
$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("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)))
)));
[]
Контроль и самоанализ
Ранее мы использовали fields_get()
для запроса модели и с самого начала использовали произвольную модель данных, Odoo хранит большинство метаданных модели внутри нескольких мета моделей, что позволяет, как делать запросы к системе так и изменять модели данных и поля (с некоторыми ограничениями) на лету через XML-RPC.
ir.model
Предоставляет информацию о моделях Odoo через различные поля
name
- понятное человеку описание модели
model
- имя каждой модели в системе
state
- Была ли модель сгенерирована в коде Python (
base
) или же создана запись вir.model
(manual
) field_id
- Список полей модели связанных через
One2many
с ir.model.fields view_ids
One2many
в Представления, определенные для моделиaccess_ids
One2many
ссылается на Контроль доступа, установленного для модели
ir.model
можно использовать для
- опрашивать систему об установленных моделях (в качестве предварительного условия для работы с моделью или для изучения содержимого системы)
- получить информацию о конкретной модели (как правило, путем перечисления полей, связанных с ней)
- динамически создавать новые модели с помощью удаленного вызова процедур (RPC)
Предупреждение
- «произвольное» имя модели данных должно начинаться с
x_
- поле
state
должно иметь значениеmanual
, в противном случае модель данных не загрузится - Невозможно добавлять новые методы в пользовательскую модель, только поля
Пользовательская модель данных первоначально будет содержать только «встроенные» поля, доступные для всех моделей:
- Python 2
- PHP
- Ruby
- Java
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', 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', [{
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(
"execute_kw", asList(
db, uid, password,
"ir.model", "create",
asList(new HashMap<String, Object>() {{
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<String, Object> () {{
put("attributes", asList(
"string",
"help",
"type"));
}}
));
{
"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"
}
}
ir.model.fields
Предоставляет информацию о полях моделей Odoo и позволяет добавлять настраиваемые поля без использования кода Python
model_id
Many2one
ссылается на ir.model, к которому принадлежит полеname
- техническое имя поля (используется в работе методов``read`` или
write
) field_description
- понятное для человека описание поля (например
string
вfields_get
) ttype
- type (тип) создаваемого поля
state
- было ли поле создано с помощью кода Python (
base
) или черезir.model.fields
(manual
) required
,readonly
,translate
- Включает соответствующий флаг на поле
groups
- field-level access control, a
Many2many
кres.groups
selection
,size
,on_delete
,relation
,relation_field
,domain
- типозависимые свойства и настройки, смотрите детальное описание полей для более подробного понимания
Как и в пользовательских моделях , в качестве фактических полей модели активируются только новые поля, созданные с помощью state="manual"
.
Предупреждение
Вычисленные поля не могут быть добавлены через ir.model.fields
, некоторая мета-информация поля (defaults, onchange)) не может быть установлена
- Python 2
- PHP
- Ruby
- 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]])
$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]])
final Integer id = (Integer)models.execute(
"execute_kw", asList(
db, uid, password,
"ir.model", "create",
asList(new HashMap<String, Object>() {{
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<String, Object>() {{
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<String, Object>() {{
put("x_name", "test record");
}})
));
client.execute(
"execute_kw", asList(
db, uid, password,
"x_custom", "read",
asList(asList(record_id))
));
[
{
"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"
}
]