Посилання Javascript¶
У цьому документі представлено фреймворк Javascript Odoo. Цей фреймворк не є великою програмою з точки зору рядків коду, але він є досить загальним, тому що в основному це машина для перетворення декларативного опису інтерфейсу в живу програму, здатну взаємодіяти з кожною моделлю та записами в базі даних. Можна навіть використовувати веб-клієнт для зміни інтерфейсу веб-клієнта.
Огляд¶
Фреймворк Javascript розроблено для роботи з трьома основними варіантами використання:
веб-клієнт: це приватний веб-додаток, де можна переглядати та редагувати бізнес-дані. Це односторінковий додаток (сторінка ніколи не перезавантажується, лише нові дані завантажуються із сервера, коли це необхідно)
веб-сайт: це публічна частина Odoo. Це дозволяє неідентифікованому користувачеві переглядати певний вміст, робити покупки або виконувати багато дій як клієнт. Це класичний веб-сайт: різні маршрути з контролерами та деякий JavaScript, щоб він працював.
точка продажу: це інтерфейс для точки продажу. Це спеціалізований односторінковий додаток.
Деякий код javascript є спільним для цих трьох випадків використання та об’єднаний разом (див. нижче в розділі ресурсів). Цей документ зосередиться переважно на архітектурі веб-клієнта.
Веб-клієнт¶
Односторінковий додаток¶
Веб-клієнт - це односторінковий застосунок: замість того, щоб запитувати повну сторінку від сервера щоразу, коли користувач виконує дію, він завантажує лише те, що потрібно для оновлення інтерфейсу користувача (UI) в результаті цієї дії. При цьому він також піклується про оновлення інформації в URL-адресі, тому в більшості випадків оновлення сторінки або закриття браузера та його повторне відкриття показує те саме.
Огляд JS-коду веб-клієнта¶
Тут ми наводимо дуже короткий огляд коду веб-клієнта в доповненні web. Шляхи будуть описані відносно web/static/src. Наступний опис навмисно не є вичерпним; метою є лише дати читачеві загальне уявлення про архітектуру.
module_loader.js: це файл, який визначає систему модулів JavaScript Odoo. Його потрібно завантажити перед будь-яким іншим JS-модулем.core/: ця папка містить код, що формує найнижчий рівень фреймворку javascript і який можна використовувати як у веб-клієнті, так і на веб-сайті, порталі та в додатку для точок продажу.weblient/: ця папка містить файли, що стосуються лише веб-клієнта та не можуть бути використані на веб-сайті або в точці продажу, такі як менеджер дій та служба дій.webclient/webclient.js: це власне компонент webclient. Він здебільшого є обгорткою для контейнера дій та панелі навігації та виконує кілька речей, необхідних під час запуску програми, таких як завантаження стану URL-адреси.webclient/actions/: ця папка містить код, відповідальний за відображення та перемикання між діями.views/: ця папка містить код для інфраструктури представлень, а також більшість представлень (деякі типи представлень додаються іншими доповненнями).views/fields/: містить визначення різних компонентів поля, а також деякі утиліти, що використовуються кількома полями.search/усі ці файли визначають вигляд пошуку (це не вигляд з точки зору веб-клієнта, лише з точки зору сервера)
Що робити, якщо файл не завантажується/оновлюється¶
Є багато різних причин, чому файл може не завантажуватися належним чином. Ось кілька речей, які ви можете спробувати вирішити проблему:
Переконайтеся, що ви зберегли свій файл; забути це зробити трапляється навіть з найкращими з нас.
Погляньте на консоль (в інструментах розробника, зазвичай відкривається за допомогою F12) і перевірте наявність помилок.
Спробуйте додати
console.log()на початку вашого файлу, щоб побачити, чи завантажено файл. Якщо він не завантажений, можливо, він не знаходиться у відповідному пакеті ресурсів, або пакет ресурсів може бути неоновленим.Залежно від ваших налаштувань, сервер може не перегенерувати пакети ресурсів після зміни файлу; є кілька варіантів вирішення цієї проблеми:
перезапуск сервера змусить його перевірити, чи пакет ресурсів оновлений, під час наступного запиту
у режимі налагодження в меню налагодження (кнопка на панелі навігації) є опція, яка дозволяє змусити сервер відновлювати пакет ресурсів на льоту без перезавантаження.
запуск сервера з опцією
--dev=xmlзмусить сервер перевіряти актуальність пакета ресурсів щоразу, коли його запитують. Радимо використовувати цю опцію під час активної розробки, але не у продакшені.
Обов’язково оновіть сторінку після зміни коду. Odoo наразі не має механізму гарячого перезавантаження модулів.
Завантаження коду Javascript¶
Великі додатки зазвичай розбиваються на менші файли, які потрібно об’єднати. Для деяких файлів може знадобитися код, визначений в іншому файлі. Існує два способи спільного використання коду між файлами:
використання глобальної області видимості (об’єкта window) для читання/запису посилань на деякі об’єкти або функції,
використання системи модулів, яка забезпечить спосіб експорту або імпорту значень для кожного модуля та забезпечить їх завантаження у правильному порядку.
Хоча працювати в глобальному масштабі можливо, це має низку проблем:
Важко забезпечити нерозголошення деталей реалізації: оголошення функцій у глобальній області видимості доступні для всього іншого коду.
Існує єдиний простір імен, що створює великий потенціал для конфліктів імен.
Залежності є неявними: якщо один фрагмент коду залежить від іншого, порядок їх завантаження важливий, але його важко гарантувати.
Використання системи модулів допомагає вирішити ці проблеми: оскільки модулі визначають свої залежності, система модулів може завантажувати їх у правильному порядку або видавати помилку, якщо залежності відсутні або є циклічними. Модулі також формують власний простір імен і можуть вибирати, що експортувати, запобігаючи розкриттю деталей реалізації та колізіям імен.
Хоча ми могли б використовувати модулі ECMAScript (ES) безпосередньо, такий підхід має низку недоліків: кожен модуль ES вимагає передачі даних по мережі, що стає дуже повільним, коли у вас є сотні файлів, і багато файлів в Odoo повинні бути присутніми, незважаючи на те, що вони нічим не імпортовані, оскільки вони просто додають код, який використовуватиме фреймворк, а не навпаки.
Через це Odoo має систему пакетів ресурсів. У цих пакетах файли JavaScript є ES-модулями зі спеціальною анотацією зверху. Ці модулі будуть об’єднані разом та транспільовані для використання нашим завантажувачем модулів. Хоча ви можете писати код, який не використовує цю систему модулів, зазвичай це не рекомендується.
(див. Нативні модулі Javascript)
Patching classes¶
Хоча ми докладаємо всіх зусиль, щоб забезпечити точки розширення, які цього не потребують, іноді необхідно змінити поведінку існуючого класу на місці. Мета полягає в тому, щоб мати механізм для зміни класу та всіх майбутніх/теперішніх екземплярів. Це робиться за допомогою допоміжної функції patch:
/** @odoo-module */
import { Hamster } from "@web/core/hamster"
import { patch } from "@web/core/utils/patch";
patch(Hamster.prototype, {
sleep() {
super.sleep(...arguments);
console.log("zzzz");
},
});
Під час виправлення методів вам потрібно виправити прототип класу, але якщо ви хочете виправити статичну властивість класу, вам потрібно виправити сам клас.
Виправлення – це небезпечна операція, і її слід виконувати обережно, оскільки вона змінить усі екземпляри класу, навіть якщо вони вже створені. Щоб уникнути дивних проблем, виправлення слід застосовувати якомога швидше, на верхньому рівні вашого модуля. Виправлення класів під час виконання може призвести до надзвичайно складних для налагодження проблем, якщо екземпляр класу вже створено.
Реєстри¶
Поширеною потребою в екосистемі Odoo є розширення/зміна поведінки базової системи ззовні (шляхом встановлення додатків, тобто іншого модуля). Наприклад, може знадобитися додати новий віджет поля в деякі представлення. У цьому випадку, та в багатьох інших, звичайний процес полягає у створенні потрібного компонента, а потім додаванні його до реєстру (крок реєстрації), щоб решта веб-клієнта знала про його існування.
У системі доступно кілька реєстрів. Реєстри, що використовуються фреймворком, – це категорії в головному реєстрі, які можна імпортувати з @web/core/registry
- поле реєстру
Реєстр полів містить усі віджети полів, відомі веб-клієнту. Щоразу, коли представленню (як правило, формі чи списку/канбану) потрібен віджет поля, він буде виглядати саме тут. Типовий варіант використання виглядає так:
import { registry } from "@web/core/registry"; class PadField extends Component { ... } registry.category("fields").add("pad", { component: PadField, supportedTypes: ["char"], // ... });
- переглянути реєстр
Цей реєстр містить усі JS-представлення, відомі веб-клієнту.
- дія реєстру
Ми відстежуємо всі дії клієнта в цьому реєстрі. Саме тут менеджер дій шукає інформацію, коли йому потрібно створити дію клієнта. Дії клієнта можуть бути функцією - функція буде викликана під час виклику дії, а повернене значення буде виконано як наступна дія, якщо це необхідно, - або компонентом Owl, який буде відображено під час виконання цієї дії.
Послуги¶
У веб-клієнті є деякі проблеми, які не може вирішити один компонент, оскільки проблема є глобальною, включає багато компонентів або потребує підтримки певного стану протягом усього часу роботи програми.
Сервіси є рішенням цих проблем: вони створюються під час запуску додатку, доступні компонентам через hook useService та залишаються активними протягом усього терміну служби додатку.
Наприклад, у нас є сервіс orm, завданням якого є забезпечення взаємодії з бізнес-об’єктами на сервері.
Ось спрощений приклад реалізації сервісу orm:
import { registry } from "@web/core/registry";
export const OrmService = {
start() {
return {
read(...) { ... },
write(...) { ... },
unlink(...) { ... },
...
}
},
};
registry.category("services").add("orm", OrmService);
Використання сервісів¶
Сервіси доступні в середовищі, але зазвичай їх слід використовувати через hook useService, який запобігає виклику методів сервісу після знищення компонента та запобігає подальшому виконанню коду після виклику методу, якщо компонент був знищений під час виклику.
class SomeComponent extends Component {
setup() {
this.orm = useService("orm");
}
// ...
getActivityModelViewID(model) {
return this.orm.call(model, "get_activity_view_id", this.params);
}
}
Розмова з сервером¶
Зазвичай існує два випадки використання під час роботи з Odoo: може знадобитися викликати метод на моделі (python) (це відбувається через контролер /web/dataset/call_kw), або може знадобитися безпосередньо викликати контролер (доступний на певному маршруті).
Виклик методу в моделі Python здійснюється через сервіс orm:
return this.orm.call("some.model", "some_method", [some, args]);
Безпосередній виклик контролера здійснюється через службу rpc:
return this.rpc("/some/route/", { some: param, });
Примітка
Служба rpc насправді не виконує те, що зазвичай розуміється як віддалений виклик процедур (RPC), але з історичних причин в Odoo ми зазвичай називаємо будь-який мережевий запит, виконаний у JavaScript, RPC. Як було зазначено в попередньому абзаці, якщо ви хочете викликати метод у моделі, вам слід використовувати службу orm.
Повідомлення¶
Фреймворк Odoo має стандартний спосіб передачі різноманітної інформації користувачеві: сповіщення, які відображаються у верхньому правому куті інтерфейсу користувача. Типи сповіщень відповідають уривкам завантаження:
info: корисно для відображення інформаційного зворотного зв’язку як наслідок дії, яка не може завершитися невдачею.
success: користувач виконав дію, яка іноді може завершитися невдачею, але цього не сталося.
попередження: користувач виконав дію, яку можна було виконати лише частково. Також корисно, якщо щось не так, але не було спричинено безпосередньо користувачем або не є особливо небезпечним.
success: користувач спробував виконати дію, але її не вдалося завершити.
Сповіщення також можна використовувати, щоб поставити запитання користувачеві, не порушуючи його робочий процес: наприклад, телефонний дзвінок, отриманий через VoIP: може відображатися закріплене сповіщення з двома кнопками Прийняти або Відхилити.
Відображення сповіщень¶
Існує два способи відображення сповіщень в Odoo:
Сервіс сповіщень дозволяє компоненту відображати сповіщення з JS-коду, викликаючи метод add.
Клієнтська дія display_notification дозволяє ініціювати відображення сповіщення з Python (наприклад, у методі, який викликається, коли користувач натискає на кнопку типу об’єкт). Ця клієнтська дія використовує службу сповіщень.
Сповіщення мають кілька опцій:
заголовок: рядок, необов’язковий. Це буде відображатися зверху як заголовок.
повідомлення: рядок, необов’язково. Вміст сповіщення. Може бути об’єктом розмітки для відображення форматованого тексту.
закріплене: логічне значення, необов’язкове (за замовчуванням false). Якщо true, сповіщення залишатиметься, доки користувач його не закриє. В іншому випадку сповіщення буде автоматично закрито після короткої затримки.
тип: рядок, необов’язковий (за замовчуванням «попередження»). Визначає стиль сповіщення. Можливі значення: «info», «success», «warning», «danger»
className: рядок, необов’язковий. Це назва класу CSS, яка буде автоматично додана до сповіщення. Це може бути корисним для стилізації, хоча його використання не рекомендується.
Ось кілька прикладів того, як відображати сповіщення в JS:
// note that we call _t on the text to make sure it is properly translated.
this.notification.add({
title: _t("Success"),
message: _t("Your signature request has been sent.")
});
this.notification.add({
title: _t("Error"),
message: _t("Filter name is required."),
type: "danger",
});
А на Python:
# note that we call _(string) on the text to make sure it is properly translated.
def show_notification(self):
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Your signature request has been sent.'),
'sticky': False,
}
}
Системний трей¶
Системний трей - це права частина навігаційної панелі інтерфейсу, де веб-клієнт відображає кілька віджетів, таких як меню обміну повідомленнями.
Коли панель навігації створює системний трей, вона шукатиме всі зареєстровані елементи системного трея та відображатиме їх.
Наразі немає спеціального API для елементів системного лотка. Вони є компонентами Owl і можуть взаємодіяти зі своїм середовищем так само, як і інші компоненти, наприклад, взаємодіючи з сервісами.
Додавання нового елемента Systray¶
Елементи можна додавати до системного лотка, додавши їх до реєстру «systray»:
import { registry } from "@web/core/registry"
class MySystrayComponent extends Component {
...
}
registry.category("systray").add("MySystrayComponent", MySystrayComponent, { sequence: 1 });
Елементи в системному треї впорядковані відповідно до їхньої послідовності в реєстрі системного трея.
Управління перекладами¶
Деякі переклади виконуються на стороні сервера (в основному всі текстові рядки, що відображаються або обробляються сервером), але в статичних файлах є рядки, які потрібно перекласти. Наразі це працює так:
кожен рядок, що перекладається, позначено спеціальною функцією _t
ці рядки використовуються сервером для створення відповідних файлів PO
кожного разу, коли веб-клієнт завантажується, він викликає маршрут /web/webclient/translations, який повертає список усіх термінів, які можна перекладати
під час виконання, щоразу, коли викликається функція
_t, вона шукатиме у цьому списку переклад і повертатиме його або оригінальний рядок, якщо його не знайдено.
Зауважте, що переклади пояснюються більш детально, з точки зору сервера, у документі Переклад модулів.
import { _t } from "@web/core/l10n/translation";
class SomeComponent extends Component {
static exampleString = _t("this should be translated");
...
someMethod() {
const str = _t("some text");
}
}
Зверніть увагу, що використання функції перекладу вимагає певної обережності: рядок, наданий як аргумент, не може бути динамічним, оскільки він статично витягується з коду для створення PO-файлів і служить ідентифікатором терміна для перекладу. Якщо вам потрібно вставити динамічний вміст у рядок, _t підтримує заповнювачі:
import { _t } from "@web/core/l10n/translation";
const str = _t("Hello %s, you have %s unread messages.", user.name, unreadCount);
Зверніть увагу, як фіксовано сам рядок. Це дозволяє функції перетворення отримати перекладений рядок перед використанням його для інтерполяції.
Сесія¶
Веб-клієнту потрібна певна інформація з Python для належного функціонування. Щоб уникнути додаткового циклу обробки запитів із сервером через мережевий запит у JavaScript, ця інформація серіалізується безпосередньо на сторінці та доступна в JS через модуль @web/session.
Додавання інформації до сесії¶
Коли маршрут /web завантажується, сервер вставляє цю інформацію в тег скрипта. Інформація отримується шляхом виклику методу session_info моделі ir.http. Ви можете перевизначити цей метод, щоб додати інформацію до повернутого словника.
from odoo import models
from odoo.http import request
class IrHttp(models.AbstractModel):
_inherit = 'ir.http'
def session_info(self):
result = super(IrHttp, self).session_info()
result['some_key'] = get_some_value_from_db()
return result
Тепер значення можна отримати в javascript, прочитавши його під час сеансу:
import { session } from "@web/session"
const myValue = session.some_key;
...
Зверніть увагу, що цей механізм розроблений для зменшення обсягу зв’язку, необхідного для готовності веб-клієнта. Він підходить лише для даних, обчислення яких є дешевим (повільний виклик session_info затримає завантаження веб-клієнта для всіх), а також для даних, які потрібні на ранній стадії процесу ініціалізації.
Представлення¶
Слово «представдення» має більше одного значення. Цей розділ стосується дизайну коду javascript для виглядів, а не структури архітектурної структури чи чогось іншого.
Хоча представлення є просто компонентами owl, вбудовані представлення загалом мають однакову структуру: компонент під назвою «SomethingController», який є коренем представлення. Цей компонент створює екземпляр деякої «моделі» (об’єкта, відповідального за керування даними) та має підкомпонент під назвою «renderer», який обробляє логіку відображення.
Поля¶
Значна частина досвіду веб-клієнта стосується редагування та створення даних. Більшість цієї роботи виконується за допомогою віджетів полів, які знають тип поля та конкретні деталі того, як значення має відображатися та редагуватися.
Декоратори¶
Як і у списку, віджети полів мають просту підтримку декорацій. Мета декорацій - надати простий спосіб визначення кольору тексту залежно від поточного стану запису. Наприклад:
<field name="state" decoration-danger="amount < 10000"/>
Допустимі назви декоратора:
decoration-bfdecoration-itdecoration-dangerdecoration-infodecoration-muteddecoration-primarydecoration-successdecoration-warning
Кожен декоратор decoration-X буде зіставлен з класом css text-X, який є стандартним початковим класом css (за винятком text-it і text-bf, які обробляються odoo і відповідають курсив і жирний відповідно). Зауважте, що значенням атрибута decoration має бути дійсний вираз Python, який буде оцінюватися разом із записом як контекстом оцінки.
Нереляційні поля¶
Тут ми документуємо всі нереляційні поля, доступні за замовчуванням, без певного порядку.
- Ціле число (
integer) Це тип поля за замовчуванням для полів типу
integer.Підтримувані типи полів:
integer
Варіанти:
type: встановлення типу вхідних даних ("text"за замовчуванням, можна встановити для"number")У режимі редагування поле відображається як вхідні дані з типом атрибута HTML, встановленим на
"number"(тому користувач може скористатися перевагами вбудованої підтримки, особливо на мобільних пристроях). У цьому випадку форматування за замовчуванням вимкнено, щоб уникнути несумісності.<field name="int_value" options="{'type': 'number'}" />
step: встановити крок на значення вгору та вниз, коли користувач натискає на кнопки (лише для введення номера типу, за замовчуванням1)<field name="int_value" options="{'type': 'number', 'step': 100}" />
format: чи має бути число відформатовано. (за замовчуваннямtrue)За замовчуванням числа форматуються відповідно до параметрів локалі. Цей параметр запобігатиме форматуванню значення поля.
<field name="int_value" options='{"format": false}' />
- Число з комою (
float) Це тип поля за замовчуванням для полів типу
float.Підтримувані типи полів:
float
Атрибути:
digits: відображена точність<field name="factor" digits="[42,5]" />
Варіанти:
type: встановлення типу вхідних даних ("text"за замовчуванням, можна встановити для"number")У режимі редагування поле відображається як вхідні дані з типом атрибута HTML, встановленим на
"number"(тому користувач може скористатися перевагами вбудованої підтримки, особливо на мобільних пристроях). У цьому випадку форматування за замовчуванням вимкнено, щоб уникнути несумісності.<field name="int_value" options="{'type': 'number'}" />
step: встановити крок на значення вгору та вниз, коли користувач натискає на кнопки (лише для введення номера типу, за замовчуванням1)<field name="int_value" options="{'type': 'number', 'step': 0.1}" />
format: чи має бути число відформатовано. (за замовчуваннямtrue)За замовчуванням числа форматуються відповідно до параметрів локалі. Цей параметр запобігатиме форматуванню значення поля.
<field name="int_value" options="{'format': false}" />
- Час (
float_time) Мета цього віджета - коректно відображати значення з плаваючою комою, яке представляє часовий інтервал (у годинах). Наприклад,
0.5слід форматувати як0:30, або4.75відповідає4:45.Підтримувані типи полів:
float
- Коефіцієнт числа з плаваючою комою (
float_factor) Цей віджет має на меті коректно відображати значення з плаваючою комою, яке було конвертовано з використанням коефіцієнта, заданого в його налаштуваннях. Наприклад, якщо значення, збережене в базі даних, дорівнює
0.5, а коефіцієнт -3, значення віджета має бути відформатовано як1.5.Підтримувані типи полів:
float
- Перемикач числа з плаваючою комою (
float_toggle) Мета цього віджета - замінити поле введення кнопкою, що містить діапазон можливих значень (заданих у налаштуваннях). Кожне клацання дозволяє користувачеві перемикатися між діапазонами. Мета полягає в тому, щоб обмежити значення поля заздалегідь визначеним вибором. Також віджет підтримує перетворення коефіцієнтів як віджет
float_factor(результатом перетворення мають бути значення діапазону).Підтримувані типи полів:
float
<field name="days_to_close" widget="float_toggle" options="{'factor': 2, 'range': [0, 4, 8]}" />
- Булеве значення (
boolean) Це тип поля за замовчуванням для полів типу
boolean.Підтримувані типи полів:
boolean
- Символ (
char) Це тип поля за замовчуванням для полів типу
char.Підтримувані типи полів:
char
- Дата (
date) Це тип поля за замовчуванням для полів типу
date. Він складається з текстового поля та засобу вибору дати.Підтримувані типи полів:
date
Варіанти:
min_date/max_date: встановлює граничні дати для прийнятних значень. За замовчуванням найдавніша прийнятна дата - 1000-01-01, а найпізніша - 9999-12-31. Прийнятні значення - це дати у форматі SQL (yyyy-MM-dd HH:mm:ss) або"сьогодні".<field name="datefield" options="{'min_date': 'today', 'max_date': '2023-12-31'}" />
warn_future: відображає попередження, якщо значення знаходиться в майбутньому (на основі сьогоднішнього дня).
<field name="datefield" options="{'warn_future': true}" />
- Дата та час (
datetime) Це тип поля за замовчуванням для полів типу
datetime. Значення завжди вказані в часовому поясі клієнта.Підтримувані типи полів:
datetime
Варіанти:
див. опції Поле дати
rounding: приріст, який використовується для генерації доступних хвилин у виборі часу. Це не впливає на фактичне значення, лише на кількість доступних опцій у випадаючому списку (за замовчуванням:5).<field name="datetimefield" options="{'rounding': 10}" />
show_time: якщо встановити значення false, частина часу приховується в полі datetime. Поле все ще прийматиме значення datetime, але частина часу буде прихована в інтерфейсі користувача (за замовчуванням:true).<field name="datetimefield" widget="datetime" options="{'show_time': false}" />
- Діапазон дат (
daterange) Цей віджет дозволяє користувачеві вибрати дату початку та завершення з одного засобу вибору.
Підтримувані типи полів:
date,datetime
Варіанти:
див. опції Поле дати або Поле дати та часу
start_date_field: поле, яке використовується для отримання/встановлення початкового значення діапазону дат (не можна використовувати зend_date_field).<field name="end_date" widget="daterange" options="{'start_date_field': 'start_date'}" />
end_date_field: поле, яке використовується для отримання/встановлення кінцевого значення діапазону дат (не можна використовувати зstart_date_field).<field name="start_date" widget="daterange" options="{'end_date_field': 'end_date'}" />
- Залишок днів (
remaining_days) Цей віджет можна використовувати для полів дати та дати й часу. У режимі лише для читання він відображає різницю (у днях) між значенням поля та сьогоднішнім днем. У режимі редагування віджет перетворюється на звичайне поле дати або дати й часу.
Підтримувані типи полів:
date,datetime
- Грошовий (
monetary) Це тип поля за замовчуванням для полів типу
monetary. Він використовується для відображення валюти. Якщо в опції вказано поле валюти, буде використано саме її, інакше буде повернуто до валюти за замовчуванням (у сеансі).Підтримувані типи полів:
monetary,float
Варіанти:
currency_field: інша назва поля, яка має бути типу many2one для валюти.<field name="value" widget="monetary" options="{'currency_field': 'currency_id'}" />
- Текст (
text) Це тип поля за замовчуванням для полів типу
text.Підтримувані типи полів:
text
- Ручка (
handle) Завдання цього поля - відображатися як
handleі дозволяти змінювати порядок різних записів шляхом їх перетягування.Попередження
Його необхідно вказати в полі, за яким сортуються записи.
Попередження
Наявність кількох полів із handle віджетом в одному списку не підтримується.
Підтримувані типи полів:
integer
- Електронна пошта (
email) У цьому полі відображається адреса ел. пошти. Основною причиною його використання є те, що він відображається як тег прив’язки з правильним href у режимі лише для читання.
Підтримувані типи полів:
char
- Телефон (
phone) У цьому полі відображається номер телефону. Основною причиною його використання є те, що він відображається як тег прив’язки з правильним href у режимі лише для читання, але лише в деяких випадках: ми хочемо зробити його доступним для натискання, лише якщо пристрій може викликати цей конкретний номер.
Підтримувані типи полів:
char
- URL (
url) У цьому полі відображається URL-адреса (у режимі лише для читання). Основною причиною його використання є те, що він відображається як тег прив’язки з відповідними класами css і href.
Крім того, текст тегу прив’язки можна налаштувати за допомогою атрибута text (це не змінить значення href).
Підтримувані типи полів:
char
<field name="foo" widget="url" text="Some URL" />
Варіанти:
website_path: (за замовчуванням:false) за замовчуванням віджет змушує (якщо ще не встановлено) значення href починатися з"http://", окрім випадків, коли для цього параметра встановлено значенняtrue, що дозволяє перенаправлення на власний вебсайт бази даних.
- Домен (
domain) Поле
domainдозволяє користувачеві створювати домени з технічним префіксом за допомогою деревоподібного інтерфейсу та переглядати вибрані записи в режимі реального часу. У режимі налагодження також є поле введення, яке дозволяє безпосередньо вводити префікс char domain (або створювати розширені домени, які не підтримуються деревоподібним інтерфейсом).Зверніть увагу, що це обмежено статичними доменами (без динамічних виразів або доступу до контекстної змінної).
Підтримувані типи полів:
char
- Кнопка посилання (
link_button) Віджет
LinkButtonнасправді просто відображає діапазон із значком та текстовим значенням як вмістом. Посилання є клікабельним і відкриє нове вікно браузера зі значенням у вигляді URL-адреси.Підтримувані типи полів:
char
- Файл зображення (
image) Цей віджет використовується для представлення двійкового значення у вигляді зображення. У деяких випадках сервер повертає
bin_sizeзамість реального зображення (bin_size- це рядок, що представляє розмір файлу, наприклад"6.5kb"). У цьому випадку віджет створить зображення з атрибутом джерела, що відповідає зображенню на сервері.Підтримувані типи полів:
binary
Варіанти:
preview_image: якщо зображення завантажується лише якbin_size, то ця опція корисна для інформування веб-клієнта про те, що ім’я поля за замовчуванням - це не назва поточного поля, а назва іншого поля.<field name="image" widget="image" options="{'preview_image': 'image_128'}" />
accepted_file_extensions: розширення файлу, яке користувач може вибрати у діалоговому вікні введення файлу (значення за замовчуванням —"image/*")(cf:
acceptатрибут в<input type="file" />)
- Бінарний файл (
binary) Загальний віджет, який дозволяє зберігати/завантажувати двійковий файл.
Підтримувані типи полів:
binary
Атрибути:
filename: збереження бінарного файлу призведе до втрати назви файлу, оскільки зберігається лише бінарне значення. Назву файлу можна зберегти в іншому полі. Для цього атрибутfilenameслід встановити для поля, присутнього у представленні.<field name="datas" filename="datas_fname" />
Варіанти:
accepted_file_extensions: розширення файлу, яке користувач може вибрати у діалоговому вікні введення файлу(cf:
acceptатрибут в<input type="file" />)
- Пріоритет (
priority) Цей віджет відображається як набір зірочок, що дозволяє користувачеві натиснути на нього, щоб вибрати значення чи ні. Це корисно, наприклад, щоб позначити завдання як високопріоритетне.
Зверніть увагу, що цей віджет також працює в режимі
readonly, що незвично.Підтримувані типи полів:
selection
- Вкладене зображення (
attachment_image) Віджет зображення для полів
many2one. Якщо поле встановлено, цей віджет буде відображатися як зображення з правильною URL-адресою джерела. Цей віджет не має іншої поведінки в режимі редагування або лише для читання, він корисний лише для перегляду зображення.Підтримувані типи полів:
many2one
<field name="displayed_image_id" widget="attachment_image" />
- Вибір мітки (
label_selection) Цей віджет відображає просту нередагуєму мітки. Це корисно лише для відображення певної інформації, а не для її редагування.
Підтримувані типи полів:
selection
Варіанти:
classes: відображення значення вибору в назву класу CSS<field name="state" widget="label_selection" options="{ 'classes': { 'draft': 'default', 'cancel': 'default', 'none': 'danger', }, }" />
- Вибір стану (
state_selection) Це спеціалізований віджет вибору. Він передбачає, що запис має деякі жорстко задані поля, присутні в поданні:
stage_id,legend_normal,legend_blocked,legend_done. Він в основному використовується для відображення та зміни стану завдання в проєкті, а додаткова інформація відображається в спадному меню.Підтримувані типи полів:
selection
<field name="kanban_state" widget="state_selection" />
- Вибір стану – Представлення список (
list.state_selection) У представленні список поле
state_selectionза замовчуванням відображає підпис поруч із піктограмою.Підтримувані типи полів:
selection
Варіанти:
hide_label: приховати мітку поруч із іконкою<field name="kanban_state" widget="state_selection" options="{'hide_label': true}" />
- Улюблене (
boolean_favorite) Цей віджет відображається як порожня (чи ні) зірочка, залежно від логічного значення. Зверніть увагу, що його також можна редагувати в режимі лише для читання.
Підтримувані типи полів:
boolean
- Перемикач (
boolean_toggle) Відображає перемикач для представлення логічного значення. Це підполе поля
boolean, яке здебільшого використовується для іншого вигляду.Підтримувані типи полів:
boolean
- Статистична інформація (
statinfo) Цей віджет призначений для представлення статистичної інформації у вигляді
stat button. Це, по суті, просто мітка з числом.Підтримувані типи полів:
integer,float
Варіанти:
label_field: якщо вказано, віджет використовуватиме значенняlabel_fieldяк текст.<button name="%(act_payslip_lines)d" icon="fa-money" type="action" > <field name="payslip_count" widget="statinfo" string="Payslip" options="{'label_field': 'label_tasks'}" /> </button>
- Відсотковий круг (
percentpie) Цей віджет призначений для відображення статистичної інформації у вигляді
stat button. Він схожий на віджет statinfo, але інформація відображається у вигляді кругової діаграми (від порожньої до повної). Зверніть увагу, що значення інтерпретується як відсоток (число від0до100).Підтримувані типи полів:
integer,float
<field name="replied_ratio" string="Replied" widget="percentpie" />
- Індикатор прогресу (
progressbar) Представити значення у вигляді індикатора прогресу (від 0 до певного значення)
Підтримувані типи полів:
integer,float
Варіанти:
editable: логічне значення, яке визначає, чи можна редагуватиvaluecurrent_value: отримати поточне значення з поля, яке має бути присутнім у представленніmax_value: отримати максимальне значення з поля, яке має бути присутнім у представленніedit_max_value: булеве значення, яке визначає, чи можна редагуватиmax_valuetitle: заголовок панелі, що відображається у верхній частині панелі-> не перекладено, використовуйте атрибут
title(не опцію), якщо термін потрібно перекласти
<field name="absence_of_today" widget="progressbar" options="{ 'current_value': 'absence_of_today', 'max_value': 'total_employee', 'editable': false, }" />
- Графік інф. панелі журналу (
dashboard_graph) Це більш спеціалізований віджет, корисний для відображення графіка, що представляє набір даних. Наприклад, він використовується в поданні канбан на панелі обліку.
Припускається, що поле є serialization JSON набору даних.
Підтримувані типи полів:
char
Атрибути:
graph_type: рядок, може бути або"line", або"bar"<field name="dashboard_graph_data" widget="dashboard_graph" graph_type="line" />
- Редактор Ace (
ace) Цей віджет призначений для використання в текстових полях. Він надає Ace Editor для редагування XML і Python.
Підтримувані типи полів:
char,text
- Бейдж (
bedge) Відображає значення всередині bootstrap badge pill.
Підтримувані типи полів:
char,selection,many2one
За замовчуванням значок має світло-сірий фон, але його можна налаштувати за допомогою механізму Декорація. Наприклад, щоб відобразити червоний бейдж за певної умови:
<field name="foo" widget="badge" decoration-danger="state == 'cancel'" />
Реляційні поля¶
Вибір (selection)
Підтримувані типи полів:
selectionАтрибути:
placeholder: рядок, який використовується для відображення певної інформації, коли значення не вибрано<field name="tax_id" widget="selection" placeholder="Select a tax" />
- Радіокнопка (
radio) Це підполе
FielSelection, але спеціалізоване для відображення всіх дійсних варіантів у вигляді радіокнопок.Зауважте, що якщо використовується для записів many2one, для отримання name_gets пов’язаних записів буде виконано більше rpc.
Підтримувані типи полів:
selection,many2one
Варіанти:
horizontal: якщоtrue, радіокнопки відображатимуться горизонтально.<field name="recommended_activity_type_id" widget="radio" options="{'horizontal': true}"/>
- Вибір значка (
selection_badge) Це підполе поля
selection, але спеціалізоване для відображення всіх дійсних варіантів у вигляді прямокутних значків.Підтримувані типи полів:
selection,many2one
<field name="recommended_activity_type_id" widget="selection_badge" />
- Many2one (
many2one) Віджет за замовчуванням для полів many2one.
Підтримувані типи полів:
many2one
Атрибути:
can_create: дозволити створення пов’язаних записів (має пріоритет над опцієюno_create)can_write: дозволити редагування пов’язаних записів (за замовчуванням:true)
Варіанти:
quick_create: дозволити швидке створення пов’язаних записів (за замовчуванням:true)no_create: заборонити створення пов’язаних записів - приховати обидва пункти випадаючого меню Створити «xxx» та Створити та редагувати (за замовчуванням:false)no_quick_create: заборонити швидке створення пов’язаних записів - приховати пункт випадаючого меню Створити «xxx» (за замовчуванням:false)no_create_edit: приховати пункт випадаючого меню Створити та редагувати (за замовчуванням:false)create_name_field: під час створення пов’язаного запису, якщо встановлено цю опцію, значенняcreate_name_fieldбуде заповнено значенням вхідних даних (за замовчуванням:name)always_reload: логічне значення, за замовчуваннямfalse. Якщоtrue, віджет завжди виконуватиме додаткову командуname_getдля отримання значення імені. Це використовується для ситуацій, коли методname_getперевизначено (будь ласка, не робіть цього)no_open: логічне значення, за замовчуваннямfalse. Якщо встановлено значенняtrue, many2one не перенаправлятиме на запис при натисканні на нього (у режимі лише для читання)
<field name="currency_id" options="{'no_create': true, 'no_open': true}" />
- Штрих-код Many2one (
many2one_barcode) Віджет для полів
many2oneдозволяє відкрити камеру з мобільного пристрою (Android/iOS) для сканування штрих-коду.Спеціалізація поля
many2one, де користувачеві дозволено використовувати вбудовану камеру для сканування штрих-коду. Потім використовуєтьсяname_searchдля пошуку цього значення.Якщо цей віджет встановлено, а користувач не використовує мобільний застосунок, він повернеться до звичайного
many2one(Many2OneField)Підтримувані типи полів:
many2one
- Аватар Many2one (
many2one_avatar) Цей віджет підтримується лише для полів
many2one, що вказують на модель, що успадковується відimage.mixin. У режимі лише для читання він відображає зображення пов’язаного запису поруч із йогоdisplay_name. Зверніть увагу, щоdisplay_nameу цьому випадку не є клікабельним посиланням. У режимі редагування він поводиться точно так само, як звичайнийmany2one.Підтримувані типи полів:
many2one
- Аватар rористувача Many2one (
many2one_avatar_user) Цей віджет є спеціалізацією
Many2OneAvatar. Коли миша на аватарі, ми відкриваємо вікно чату з відповідним користувачем. Цей віджет можна встановити лише для полівmany2one, що вказують на модельres.users.Підтримувані типи полів:
many2one(вказує наres.users)
- Аватар співробітника Many2one(
many2one_avatar_employee) Те саме, що й
many2one_avatar_user, але для полівmany2oneвказують наhr.employee.Підтримувані типи полів:
many2one(вказує наhr.employee)
- Many2many (
many2many) Віджет за замовчуванням для полів
many2many.Підтримувані типи полів:
many2many
Атрибути:
mode: рядок, вигляд за замовчуванням для відображенняdomain: обмежити дані певним доменом
Варіанти:
create_text: дозволити налаштування тексту, що відображається під час додавання нового записуlink: домен, що визначає, чи можна додавати записи до відношення (за замовчуванням:true).unlink: домен, що визначає, чи можна видалити записи з відношення (за замовчуванням:true).
- Бінарний файл Many2many (
many2many_binary) Цей віджет допомагає користувачеві завантажувати або видаляти один або кілька файлів одночасно.
Зверніть увагу, що цей віджет є специфічним для моделі
ir.attachment.Підтримувані типи полів:
many2many
Варіанти:
accepted_file_extensions: розширення файлу, яке користувач може вибрати у діалоговому вікні введення файлу(cf:
acceptатрибут в<input type="file" />)
- Теги Many2many (
many2many_tags) Відобразити поле
many2manyяк список тегів.Підтримувані типи полів:
many2many
Варіанти:
create: домен, що визначає, чи можна створювати нові теги (за замовчуванням:true).<field name="category_id" widget="many2many_tags" options="{'create': [['some_other_field', '>', 24]]}" />
color_field: назва числового поля, яке має бути присутнім у поданні. Колір буде вибрано залежно від його значення.<field name="category_id" widget="many2many_tags" options="{'color_field': 'color'}" />
no_edit_color: встановити значенняtrue, щоб виключити можливість зміни кольору тегів (за замовчуванням:false).<field name="category_id" widget="many2many_tags" options="{'color_field': 'color', 'no_edit_color': true}" />
- Теги Many2many - Представлення форми (
form.many2many_tags) Спеціалізація віджета
many2many_tagsдля представлення форм. Він містить додатковий код, що дозволяє редагувати колір тегу.Підтримувані типи полів:
many2many
- Теги Many2many - Канбан-представлення (
kanban.many2many_tags) Спеціалізація віджета
many2many_tagsдля представлення канбану.Підтримувані типи полів:
many2many
- Чекбокси Many2many (
many2many_checkboxes) Це поле відображає список чекбокссів і дозволяє користувачеві вибрати підмножину варіантів. Зверніть увагу, що кількість відображених значень обмежена до
100. Це обмеження не налаштовується. Воно просто дозволяє обробляти екстремальні випадки, коли цей віджет неправильно встановлено на полі з величезною комоделлю. У таких випадках список є більш адекватним, оскільки він дозволяє розбиття на сторінки та фільтрацію.Підтримувані типи полів:
many2many
- One2many (
one2many) Віджет за замовчуванням для полів
one2many. Зазвичай він відображає дані у вигляді підсписку або під-канбана.Підтримувані типи полів:
one2many
Варіанти:
create: домен, що визначає, чи можна створювати пов’язані записи (за замовчуванням:true).delete: домен, що визначає, чи можна видалити пов’язані записи (за замовчуванням:true).<field name="turtles" options="{'create': [['some_other_field', '>', 24]]}" />
create_text: рядок, який використовується для налаштування мітки/тексту „Додати“.<field name="turtles" options="{'create_text': 'Add turtle'}" />
- Рядок стану (
statusbar) Це поле, специфічне для представлень форм. Це панель у верхній частині багатьох форм, яка представляє потік і дозволяє вибрати певний стан.
Підтримувані типи полів:
selection,many2one
- Посилання (
reference) Поле
reference- це комбінація поля select (для моделі) та поляmany2one(для її значення). Воно дозволяє вибрати запис на довільній моделі.Підтримувані типи полів:
char,reference
Варіанти:
model_field: назва об’єктаir.model, що містить модель записів, які можна вибрати. Якщо цей параметр встановлено, частина вибору поляreferenceне відображається.
Віджети¶
- Дні тижня (
week_days) Цей віджет відображає список прапорців для днів тижня, по одному чекбоксу для кожного дня, і дозволяє користувачеві вибрати підмножину варіантів.
<widget name="week_days" />
Дії клієнта¶
Дія клієнта – це компонент, який може відображатися як головний елемент у веб-клієнті, займаючи весь простір під панеллю навігації, подібно до act_window_action. Це корисно, коли вам потрібен компонент, який не тісно пов’язаний з існуючим представленням або певною моделлю. Наприклад, додаток Обговорення є дією клієнта.
Клієнтська дія – це термін, який має різні значення залежно від контексту:
з точки зору сервера, це запис моделі ir_action з полем tag типу char
з точки зору веб-клієнта, це компонент Owl, зареєстрований у реєстрі дій під тим самим ключем, що й його тег.
Щоразу, коли елемент меню пов’язаний з дією клієнта, його відкриття просто отримає визначення дії з сервера, а потім шукатиме її тег у реєстрі дій, щоб отримати визначення компонента. Цей компонент потім буде відображено контейнером дій.
Додавання дії клієнта¶
Дія клієнта – це компонент, який керуватиме частиною екрана під панеллю навігації. Визначення дії клієнта так само просте, як створення компонента Owl та додавання його до реєстру дій.
import { registry } from "@web/core/registry";
class MyClientAction extends Component { ... }
registry.category("actions").add("my-custom-action", ClientAction);
Потім, щоб використовувати дію клієнта у веб-клієнті, нам потрібно створити запис дії клієнта (запис моделі ir.actions.client) з відповідним атрибутом tag:
<record id="my_client_action" model="ir.actions.client">
<field name="name">Some Name</field>
<field name="tag">my-custom-action</field>
</record>