Зовнішній API¶
Odoo зазвичай розширюється внутрішньо за допомогою модулів, але багато його функцій і всі його дані також доступні ззовні для зовнішнього аналізу або інтеграції з різними інструментами. Частина API Моделі легко доступна через XML-RPC і доступна з різних мов.
Важливо
Starting with PHP8, the XML-RPC extension may not be available by default. Check out the manual for the installation steps.
Примітка
Access to data via the external API is only available on Custom Odoo pricing plans. Access to the external API is not available on One App Free or Standard plans. For more information visit the Odoo pricing page or reach out to your Customer Success Manager.
Перегляньте також
Підключення¶
Налаштування¶
Якщо у вас уже встановлено сервер Odoo, ви можете просто скористатися його параметрами.
Важливо
Для екземплярів Odoo Online (<domain>.odoo.com) користувачі створюються без локального пароля (ви входите в систему через систему автентифікації Odoo Online, а не через сам екземпляр). Щоб використовувати XML-RPC в екземплярах Odoo Online, вам потрібно буде встановити пароль для облікового запису користувача, який ви хочете використовувати:
Увійдіть у свій екземпляр за допомогою облікового запису адміністратора.
Перейдіть до
.Клацніть користувача, якого ви хочете використовувати для доступу до XML-RPC.
Натисніть Дія і виберіть Змінити пароль.
Встановіть значення Новий пароль, а потім натисніть Змінити пароль.
URL-адреса сервера - це домен примірника (наприклад, https://mycompany.odoo.com), назва бази даних - це назва примірника (наприклад, mycompany). Ім’я користувача - це налаштоване ім’я користувача, як показано на екрані Змінити пароль.
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)>;
var (
url = <insert server URL>
db = <insert database name>
username = "admin"
password = <insert password for your admin user (default: admin)>
)
API ключі¶
Нове в версії 14.0.
Odoo підтримує ключі API і (залежно від модулів або налаштувань) може вимагати ці ключі для виконання операцій веб-сервісу.
Щоб використовувати ключі API у своїх сценаріях, просто замініть свій пароль на ключ. Логін залишається у використанні. Ви повинні зберігати ключ API так само ретельно, як і пароль, оскільки вони, по суті, надають той самий доступ до вашого облікового запису користувача (хоча їх не можна використовувати для входу через інтерфейс).
Щоб додати ключ до свого облікового запису, просто перейдіть у Налаштування (або Мій профіль):

потім відкрийте вкладку Безпека облікового запису і натисніть Новий ключ API:

Введіть опис ключа, цей опис має бути максимально чітким і повним: це єдиний спосіб пізніше ідентифікувати ваші ключі та знати, чи слід їх видалити чи залишити.
Натисніть Створити ключ, а потім скопіюйте наданий ключ. Зберігайте цей ключ обережно: він еквівалентний вашому паролю, і так само, як і ваш пароль, система не зможе відновити чи показати ключ пізніше. Якщо ви втратите цей ключ, вам доведеться створити новий (і, можливо, видалити той, який ви втратили).
Після налаштування ключів у вашому обліковому записі вони з’являться над кнопкою Новий ключ API, і ви зможете їх видалити:

Видалений ключ API не можна відновити або відновити. Вам доведеться створити новий ключ і оновити всі місця, де ви використовували старий.
Тестова база даних¶
Щоб спростити дослідження, ви також можете запитати на https://demo.odoo.com тестову базу даних:
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']);
Примітка
У цих прикладах використовується бібліотека Ripcord, яка надає простий API XML-RPC. Ripcord вимагає, щоб підтримка XML-RPC була ввімкнена у вашій установці PHP.
Оскільки виклики здійснюються через HTTPS, для цього також потрібно розширення OpenSSL бути включеним.
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");
Примітка
У цих прикладах використовується бібліотека Apache XML-RPC.
Приклади не включають імпорт, оскільки цей імпорт не можна було вставити в код.
client, err := xmlrpc.NewClient("https://demo.odoo.com/start", nil)
if err != nil {
log.Fatal(err)
}
info := map[string]string{}
client.Call("start", nil, &info)
url = info["host"].(string)
db = info["database"].(string)
username = info["user"].(string)
password = info["password"].(string)
Примітка
These examples use the github.com/kolo/xmlrpc library.
Приклади не включають імпорт, оскільки цей імпорт не можна було вставити в код.
Вхід в систему¶
Odoo вимагає, щоб користувачі API пройшли автентифікацію, перш ніж вони зможуть запитувати більшість даних.
Кінцева точка xmlrpc/2/common
забезпечує мета-виклики, які не потребують автентифікації, як-от сама автентифікація чи отримання інформації про версію. Щоб переконатися, що інформація про підключення правильна перед спробою автентифікації, найпростішим викликом є запит на версію сервера. Сама автентифікація виконується за допомогою функції authenticate
і повертає ідентифікатор користувача (uid
), який використовується в автентифікованих викликах замість логіна.
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());
client, err := xmlrpc.NewClient(fmt.Sprintf("%s/xmlrpc/2/common", url), nil)
if err != nil {
log.Fatal(err)
}
common := map[string]any{}
if err := client.Call("version", nil, &common); err != nil {
log.Fatal(err)
}
Результат:
{
"server_version": "13.0",
"server_version_info": [13, 0, 0, "final", 0],
"server_serie": "13.0",
"protocol_version": 1,
}
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()));
var uid int64
if err := client.Call("authenticate", []any{
db, username, password,
map[string]any{},
}, &uid); err != nil {
log.Fatal(err)
}
Методи виклику¶
Другою кінцевою точкою є xmlrpc/2/object
. Він використовується для виклику методів моделей odoo через функцію RPC execute_kw
.
Кожен виклик execute_kw
приймає такі параметри:
база даних для використання, рядок
id користувача (отриманий через
authenticate
), ціле числопароль користувача, рядок
назва моделі, рядок
назва методу, рядок
масив/список параметрів, що передаються за позицією
зіставлення/словник параметрів для передачі за ключовим словом (необов’язково)
Example
Наприклад, щоб побачити, чи можемо ми прочитати модель res.partner
, ми можемо викликати check_access_rights
з operation
, переданим позицією, і raise_exception
, переданим ключовим словом (щоб отримати результат істина/неправда, а не істина/помилка):
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); }}
));
models, err := xmlrpc.NewClient(fmt.Sprintf("%s/xmlrpc/2/object", url), nil)
if err != nil {
log.Fatal(err)
}
var result bool
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "check_access_rights",
[]string{"read"},
map[string]bool{"raise_exception": false},
}, &result); err != nil {
log.Fatal(err)
}
Результат:
true
Список записів¶
Записи можна перераховувати та фільтрувати за допомогою search()
.
search()
використовує обов’язковий фільтр domain (можливо, порожній) і повертає ідентифікатори бази даних усіх записів, які відповідають фільтру.
Example
Щоб перерахувати компанії-клієнти, наприклад:
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)))
)));
var records []int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "search",
[]any{[]any{
[]any{"is_company", "=", true},
}},
}, &records); err != nil {
log.Fatal(err)
}
Результат:
[7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74]
Розбиття на сторінки¶
За замовчуванням пошук повертає ідентифікатори всіх записів, які відповідають умові, яких може бути величезна кількість. Параметри offset
і limit
доступні для отримання лише підмножини всіх відповідних записів.
Example
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); }}
)));
var records []int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "search",
[]any{[]any{
[]any{"is_company", "=", true},
}},
map[string]int64{"offset": 10, "limit": 5},
}, &records); err != nil {
log.Fatal(err)
}
Результат:
[13, 20, 30, 22, 29]
К-сть записів¶
Замість того, щоб отримати, можливо, гігантський список записів і підрахувати їх, search_count()
можна використовувати для отримання лише кількості записів, які відповідають запиту. Він використовує той самий фільтр domain, що й search()
і жодних інших параметрів.
Example
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)))
));
var counter int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "search_count",
[]any{[]any{
[]any{"is_company", "=", true},
}},
}, &counter); err != nil {
log.Fatal(err)
}
Результат:
19
Примітка
Виклик search
, а потім search_count
(або навпаки) може не дати узгоджених результатів, якщо інші користувачі використовують сервер: збережені дані могли змінитися між викликами.
Читайте записи¶
Дані записів доступні за допомогою методу read()
, який приймає список ідентифікаторів (як повертає search()
) і, за бажанням, список полів для отримання. За замовчуванням він отримує всі поля, які поточний користувач може прочитати, а це, як правило, величезна кількість.
Example
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();
var ids []int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "search",
[]any{[]any{
[]any{"is_company", "=", true},
}},
map[string]int64{"limit": 1},
}, &ids); err != nil {
log.Fatal(err)
}
var records []any
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "read",
ids,
}, &records); err != nil {
log.Fatal(err)
}
// count the number of fields fetched by default
count := len(records)
Результат:
121
І навпаки, вибір лише трьох полів вважається цікавим.
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"));
}}
)));
var recordFields []map[string]any
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "read",
ids,
map[string][]string{
"fields": {"name", "country_id", "comment"},
},
}, &recordFields); err != nil {
log.Fatal(err)
}
Результат:
[{"comment": false, "country_id": [21, "Belgium"], "id": 7, "name": "Agrolait"}]
Примітка
Навіть якщо поле id
не запитується, воно завжди повертається.
Список полів запису¶
fields_get()
можна використовувати для перевірки полів моделі та перевірки, які з них представляють інтерес.
Оскільки він повертає велику кількість метаінформації (вона також використовується клієнтськими програмами), її слід відфільтрувати перед друком. Найцікавішими елементами для користувача є string
(мітка поля), ``help` ` (текст довідки, якщо доступний) і `` type `` (щоб знати, які значення очікувати або надсилати під час оновлення запису).
Example
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"));
}}
));
recordFields := map[string]string{}
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "fields_get",
[]any{},
map[string][]string{
"attributes": {"string", "help", "type"},
},
}, &recordFields); err != nil {
log.Fatal(err)
}
Результат:
{
"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()
, але він також може приймати список fields
(наприклад read()
, якщо цей список не надано, він отримає всі поля відповідних записів).
Example
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);
}}
)));
var recordFields []map[string]any
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "search_read",
[]any{[]any{
[]any{"is_company", "=", true},
}},
map[string]any{
"fields": []string{"name", "country_id", "comment"},
"limit": 5,
},
}, &recordFields); err != nil {
log.Fatal(err)
}
Результат:
[
{
"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()
. Метод створює один запис і повертає його ідентифікатор бази даних.
create()
виконує зіставлення полів зі значеннями, які використовуються для ініціалізації запису. Для будь-якого поля, яке має значення за замовчуванням і не встановлене за допомогою аргументу зіставлення, буде використано значення за замовчуванням.
Example
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"); }})
));
var id int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "create",
[]map[string]string{
{"name": "New Partner"},
},
}, &id); err != nil {
log.Fatal(err)
}
Результат:
78
Оновлення записів¶
Записи можна оновити за допомогою write()
. Потрібен список записів для оновлення та зіставлення оновлених полів зі значеннями, подібними до create()
.
Кілька записів можна оновлювати одночасно, але всі вони отримають однакові значення для встановлених полів. Неможливо виконати «обчислене» оновлення (де встановлене значення залежить від існуючого значення запису).
Example
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', 'read', [[id], ['display_name']])
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', 'read', [[id], ['display_name']])
$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', 'read', array(array($id), array('display_name')));
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", "read",
asList(asList(id), asList("display_name"))
)));
var result bool
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "write",
[]any{
[]int64{id},
map[string]string{"name": "Newer partner"},
},
}, &result); err != nil {
log.Fatal(err)
}
// get record name after having changed it
var record []any
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "name_get",
[]any{
[]int64{id},
},
}, &record); err != nil {
log.Fatal(err)
}
Результат:
[[78, "Newer partner"]]
Видалення записів¶
Записи можна видаляти масово, надавши їхні ідентифікатори unlink()
.
Example
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)))
)));
var result bool
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "unlink",
[]any{
[]int64{id},
},
}, &result); err != nil {
log.Fatal(err)
}
// check if the deleted record is still in the database
var record []any
if err := models.Call("execute_kw", []any{
db, uid, password,
"res.partner", "search",
[]any{[]any{
[]any{"id", "=", id},
}},
}, &record); err != nil {
log.Fatal(err)
}
Результат:
[]
Огляд і самоспостереження¶
Хоча раніше ми використовували fields_get()
для запиту моделі та з самого початку використовували довільну модель, Odoo зберігає більшість метаданих моделі в кількох метамоделях, які дозволяють як запитувати систему, так і зміна моделей і полів (з деякими обмеженнями) на льоту через XML-RPC.
ir.model
¶
Надає інформацію про моделі Odoo через різні поля.
name
зрозумілий опис моделі
model
назву кожної моделі в системі
state
чи була модель згенерована в коді Python (
base
) чи шляхом створення записуir.model
(manual
)field_id
список полів моделі через
One2many
до ir.model.fieldsview_ids
One2many
to the View architectures defined for the modelaccess_ids
One2many
відношення до Права доступу набору в моделі
ir.model
можна використовувати для
Надсилайте запит системі щодо встановлених моделей (як передумова для операцій над моделлю або для вивчення вмісту системи).
Отримайте інформацію про конкретну модель (зазвичай перерахувавши пов’язані з нею поля).
Створюйте нові моделі динамічно через RPC.
Важливо
Назви користувацьких моделей мають починатися з
x_
.Необхідно вказати
state
і встановити значенняmanual
, інакше модель не буде завантажено.Неможливо додати нові методи до спеціальної моделі, лише поля.
Example
Спеціальна модель спочатку міститиме лише «вбудовані» поля, доступні для всіх моделей:
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"));
}}
));
var id int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"ir.model", "create",
[]map[string]string{
{
"name": "Custom Model",
"model": "x_custom_model",
"state": "manual",
},
},
}, &id); err != nil {
log.Fatal(err)
}
recordFields := map[string]string{}
if err := models.Call("execute_kw", []any{
db, uid, password,
"x_custom_model", "fields_get",
[]any{},
map[string][]string{
"attributes": {"string", "help", "type"},
},
}, &recordFields); err != nil {
log.Fatal(err)
}
Результат:
{
"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
name
технічна назва поля (використовується в
read
абоwrite
)field_description
зрозуміла мітка поля (наприклад,
string
уfields_get
)ttype
type поля для створення
state
незалежно від того, було поле створено через код Python (
base
) чи черезir.model.fields
(manual
)required
,readonly
,translate
вмикає відповідний прапорець на полі
groups
контроль доступу на рівні поля, a
Many2many
доres.groups
selection
,size
,on_delete
,relation
,relation_field
,domain
специфічні для типу властивості та налаштування див. документацію полів для деталей
Важливо
Подібно до спеціальних моделей, лише нові поля, створені за допомогою
state="manual"
, активуються як фактичні поля в моделі.Обчислені поля не можна додавати через
ir.model.fields
, деякі поля мета-інформації (за замовчуванням, onchange) також не можуть бути встановлені.
Example
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))
));
var id int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"ir.model", "create",
[]map[string]string{
{
"name": "Custom Model",
"model": "x_custom",
"state": "manual",
},
},
}, &id); err != nil {
log.Fatal(err)
}
var fieldId int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"ir.model.fields", "create",
[]map[string]any{
{
"model_id": id,
"name": "x_name",
"ttype": "char",
"state": "manual",
"required": true,
},
},
}, &fieldId); err != nil {
log.Fatal(err)
}
var recordId int64
if err := models.Call("execute_kw", []any{
db, uid, password,
"x_custom", "create",
[]map[string]string{
{"x_name": "test record"},
},
}, &recordId); err != nil {
log.Fatal(err)
}
var recordFields []map[string]any
if err := models.Call("execute_kw", []any{
db, uid, password,
"x_custom", "read",
[][]int64{{recordId}},
}, recordFields); err != nil {
log.Fatal(err)
}
Результат:
[
{
"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"
}
]