ORM API

Модуль Object Relational Mapping:
  • Ієрархічна структура

  • Узгодженість і перевірка обмежень

  • Метадані об’єкта залежать від його статусу

  • Оптимізована обробка за складним запитом (кілька дій одночасно)

  • Значення полів за замовчуванням

  • Оптимізація дозволів

  • Постійний об’єкт: DB postgresql

  • Перетворення даних

  • Багаторівнева система кешування

  • Два різних механізми успадкування

  • Багатий набір типів полів:
    • classical (varchar, integer, boolean, …)

    • relational (one2many, many2one, many2many)

    • функціональний

Моделі

Поля моделі визначаються як атрибути самої моделі:

from odoo import models, fields
class AModel(models.Model):
    _name = 'a.model.name'

    field1 = fields.Char()

Попередження

це означає, що ви не можете визначити поле та метод з однаковою назвою, останній мовчки перезапише попередні.

За замовчуванням мітка поля (назва, видима для користувача) є версією назви поля з великої літери, це можна замінити параметром string.

field2 = fields.Integer(string="Field Label")

Перелік типів полів і параметрів див. посилання на поля.

Значення за замовчуванням визначаються як параметри полів або як значення:

name = fields.Char(default="a value")

або як функція, викликана для обчислення значення за замовчуванням, яке має повернути це значення:

def _default_name(self):
    return self.get_value()

name = fields.Char(default=lambda self: self._default_name())

API

class odoo.models.BaseModel[source]

Базовий клас для моделей Odoo.

Моделі Odoo створюються шляхом успадкування одного з наступного:

  • Model для звичайних моделей, що зберігаються в базі даних

  • TransientModel для тимчасових даних, які зберігаються в базі даних, але періодично автоматично видаляються

  • AbstractModel для абстрактних суперкласів, призначених для спільного використання кількома моделями успадкування

Система автоматично створює кожну модель один раз для бази даних. Ці екземпляри представляють доступні моделі в кожній базі даних і залежать від того, які модулі встановлено в цій базі даних. Фактичний клас кожного екземпляра будується з класів Python, які створюють і успадковують відповідну модель.

Кожен екземпляр моделі є «recordset», тобто впорядкованою колекцією записів моделі. Набори записів повертаються такими методами, як browse(), search() або доступ до полів. Записи не мають явного представлення: запис представлено як recordset з одного запису.

Щоб створити клас, екземпляр якого не слід створювати, для атрибута _register можна встановити значення False.

_auto = False

Чи потрібно створити таблицю бази даних. Якщо встановлено значення False, замініть init(), щоб створити таблицю бази даних.

Автоматично встановлюється значення True для Model і TransientModel, False для AbstractModel.

Порада

Щоб створити модель без жодної таблиці, успадкуйте від AbstractModel.

_log_access

Чи повинен ORM автоматично генерувати та оновлювати Поля журналу доступу.

За замовчуванням використовується будь-яке значення, встановлене для _auto.

_table = None

Назва таблиці SQL, яка використовується моделлю, якщо _auto

_sequence = None

Послідовність SQL для використання ID поля

_sql_constraints = []

SQL constraints [(name, sql_def, message)]

_register = True

видимість реєстру

_abstract = True

Чи є модель abstract.

Перегляньте також

AbstractModel

_transient = False

Чи є модель transient.

Перегляньте також

TransientModel

_name = None

назва моделі (у крапковій нотації, простір імен модуля)

_description = None

неформальна назва моделі

_inherit = None

Моделі, успадковані від Python:

тип

str або list(str)

Примітка

  • Якщо встановлено _name, назви батьківських моделей, від яких слід успадкувати

  • Якщо _name не встановлено, назва окремої моделі буде розширено на місці

_inherits = {}

словник {„parent_model“: „m2o_field“} зіставлення _name батьківських бізнес-об’єктів з назвами відповідних полів зовнішнього ключа для використання:

_inherits = {
    'a.model': 'a_field_id',
    'b.model': 'b_field_id'
}

реалізує успадкування на основі композиції: нова модель відкриває всі поля успадкованих моделей, але не зберігає жодного з них: самі значення залишаються збереженими у зв’язаному записі.

Попередження

якщо в моделях _inherits-ed визначено декілька полів з однаковою назвою, успадковане поле відповідатиме останньому (у порядку списку успадкованих).

_rec_name = None

поле для позначення записів, за замовчуванням: name

_order = 'id'

типове поле порядку для результатів пошуку

_check_company_auto = False

Під час запису та створення викличте _check_company, щоб забезпечити узгодженість компаній у реляційних полях, які мають атрибут check_company=True.

_parent_name = 'parent_id'

поле many2one використовується як батьківське поле

_parent_store = False

встановіть значення True, щоб обчислити поле parent_path.

Поряд із полем parent_path встановлює індексоване сховище деревоподібної структури записів, щоб забезпечити швидші ієрархічні запити до записів поточної моделі за допомогою доменів child_of і parent_of оператори.

_date_name = 'date'

поле для представлення календаря за замовчуванням

_fold_name = 'fold'

поле для визначення згорнутих груп у представленнях канбан

AbstractModel

odoo.models.AbstractModel[source]

alias of odoo.models.BaseModel

Модель

class odoo.models.Model[source]

Основний супер-клас для звичайних моделей Odoo, що зберігаються в базі даних.

Моделі Odoo створюються шляхом успадкування цього класу:

class user(Model):
    ...

Пізніше система створить екземпляр класу один раз для бази даних (у якій встановлено модуль класу).

_auto = True

Чи потрібно створити таблицю бази даних. Якщо встановлено значення False, замініть init(), щоб створити таблицю бази даних.

Автоматично встановлюється значення True для Model і TransientModel, False для AbstractModel.

Порада

Щоб створити модель без жодної таблиці, успадкуйте від AbstractModel.

_abstract = False

Чи є модель abstract.

Перегляньте також

AbstractModel

_transient = False

Чи є модель transient.

Перегляньте також

TransientModel

TransientModel

class odoo.models.TransientModel[source]

Модель супер-класу для тимчасових записів, призначених для тимчасової стійкості та регулярної очистки.

TransientModel має спрощене керування правами доступу, усі користувачі можуть створювати нові записи та мати доступ лише до створених ними записів. Суперкористувач має необмежений доступ до всіх записів TransientModel.

_auto = True

Чи потрібно створити таблицю бази даних. Якщо встановлено значення False, замініть init(), щоб створити таблицю бази даних.

Автоматично встановлюється значення True для Model і TransientModel, False для AbstractModel.

Порада

Щоб створити модель без жодної таблиці, успадкуйте від AbstractModel.

_abstract = False

Чи є модель abstract.

Перегляньте також

AbstractModel

_transient = True

Чи є модель transient.

Перегляньте також

TransientModel

Поля

class odoo.fields.Field[source]

Дескриптор поля містить визначення поля та керує доступом і призначенням відповідного поля в записах. Під час створення екземпляра поля можна надати такі атрибути:

Параметри
  • string (str) – мітка поля, яке бачать користувачі; якщо не встановлено, ORM приймає назву поля в класі (з великої літери).

  • help (str) – підказка поля, яку бачать користувачі

  • invisible – чи поле невидиме (логічне, за замовчуванням False)

  • readonly (bool) – чи є поле лише для читання (за замовчуванням: False). Це впливає лише на інтерфейс користувача. Будь-яке призначення полів у коді працюватиме (якщо поле є збереженим або інверсійним полем).

  • required (bool) – чи обов’язкове значення поля (за замовчуванням: False)

  • index (bool) – чи проіндексовано поле в базі даних. Примітка: не впливає на незбережені та віртуальні поля. (за замовчуванням: False)

  • default (value or callable) – значення поля за умовчанням; це або статичне значення, або функція, яка приймає recordset і повертає значення; використовуйте default=None, щоб відхилити значення за замовчуванням для поля

  • states (dict) – словник, що відображає значення стану до списків пар атрибут-значення інтерфейсу; можливі атрибути: readonly, required, invisible. .. попередження:: Будь-яка умова на основі стану вимагає, щоб значення поля state було доступне в інтерфейсі користувача на стороні клієнта. Зазвичай це робиться шляхом включення його у відповідні перегляди, можливо, зроблені невидимими, якщо вони не стосуються кінцевого користувача.

  • groups (str) – список розділених комами xml-ідентифікаторів груп (string); це обмежує доступ до поля лише для користувачів вказаних груп

  • company_dependent (bool) – чи залежить значення поля від поточної компанії; Значення не зберігається в таблиці моделей. Він зареєстрований як ir.property. Коли потрібне значення поля company_dependent, виконується пошук у ir.property, пов’язаному з поточною компанією (і поточним записом, якщо така властивість існує). Якщо значення в записі змінено, це або змінює наявну властивість для поточного запису (якщо він існує), або створює нову для поточної компанії та res_id. Якщо значення змінено на стороні компанії, це вплине на всі записи, для яких значення не було змінено.

  • copy (bool) – чи потрібно копіювати значення поля при дублюванні запису (за замовчуванням: True для звичайних полів, False для полів one2many та обчислюваних полів, включно з полями властивостей та пов’язаними з ними полями)

  • store (bool) – чи зберігається поле в базі даних (за замовчуванням: True, False для обчислюваних полів)

  • group_operator (str) – агрегатна функція, що використовується read_group() при групуванні за цим полем. Підтримуються такі агрегатні функції: * array_agg : значення, включаючи нулі, об’єднані у масив * count : кількість рядків * count_distinct : кількість різних рядків * bool_and : true, якщо всі значення істинні, інакше false * bool_or : true, якщо хоча б одне значення істинне, інакше false * max : максимальне значення всіх значень * min : мінімальне значення всіх значень * avg : середнє арифметичне всіх значень * sum : сума всіх значень

  • group_expand (str) – функція, що використовується для розширення результатів read_group при групуванні за поточним полем. .. code-block :: python @api.model def _read_group_selection_field(self, values, domain, order): return [„choice1“, „choice2“, …] # доступні варіанти вибору. @api.model def _read_group_many2one_field(self, records, domain, order): return records + self.search([custom_domain])

Обчислювані поля

Параметри
  • compute (str) – назва методу, який обчислює поле .. див. також:: Додаткові поля/Обчислювальні поля

  • compute_sudo (bool) – чи потрібно переобчислювати поле від імені суперкористувача, щоб обійти права доступу (за замовчуванням True для збережених полів, False для незбережених полів)

  • inverse (str) – назва методу, який інвертує поле (необов’язково)

  • search (str) – назва методу, який реалізує пошук по полю (необов’язково)

  • related (str) – послідовність назв полів .. див. також:: Додаткові поля/Пов’язані поля

Основні поля

class odoo.fields.Boolean[source]

Інкапсулює bool.

class odoo.fields.Char[source]

Базове рядкове поле, може мати обмежену довжину, зазвичай відображається як однорядковий рядок у клієнтах.

Параметри
  • size (int) – максимальний розмір значень, що зберігаються для цього поля

  • trim (bool) – вказує, чи буде значення обрізано чи ні (за замовчуванням True). Зауважте, що операція обрізання застосовується лише веб-клієнтом.

  • translate (bool or callable) – увімкнути переклад значень поля; використовувати translate=True для перекладу значень поля в цілому; translate також може бути викликом, так що translate(callback, value) перекладає value, використовуючи callback(term) для отримання перекладу термінів.

class odoo.fields.Float[source]

Інкапсулює float.

Точність цифр задається (необов’язковим) атрибутом digits.

Параметри

digits (tuple(int,int) or str) – пара (total, decimal) або рядок, що посилається на ім’я запису DecimalPrecision.

Коли плаваюча величина пов’язана з одиницею виміру, важливо використовувати правильний інструмент для порівняння або округлення значень з правильною точністю.

Клас Float надає для цього декілька статичних методів:

round() округлити число з заданою точністю. is_zero() перевірити, чи дорівнює число нулю з заданою точністю. compare() порівняти два числа з заданою точністю.

Приклад

Щоб округлити число з точністю до одиниці виміру:

fields.Float.round(self.product_uom_qty, precision_rounding=self.product_uom_id.rounding)

Щоб перевірити, чи дорівнює кількість нулю з точністю до одиниці виміру:

fields.Float.is_zero(self.product_uom_qty, precision_rounding=self.product_uom_id.rounding)

Щоб порівняти дві величини:

field.Float.compare(self.product_uom_qty, self.qty_done, precision_rounding=self.product_uom_id.rounding)

Помічник порівняння використовує семантику __cmp__ в історичних цілях, тому правильним, ідіоматичним способом використання цього помічника є такий:

якщо результат == 0, то перший та другий числа дорівнюють один одному якщо результат < 0, то перший дріб менший за другий якщо результат > 0, то перший дріб більший за другий

class odoo.fields.Integer[source]

Інкапсулює int.

Розширені поля

class odoo.fields.Binary[source]

Інкапсулює двійковий вміст (наприклад, файл).

Параметри

attachment (bool) – чи слід зберігати поле як ir_attachment або у стовпчику таблиці моделі (за замовчуванням: True).

class odoo.fields.Html[source]

Інкапсулює вміст html-коду.

Параметри
  • sanitize (bool) – чи потрібно очищати значення (за замовчуванням: True)

  • sanitize_tags (bool) – чи очищати теги (приймається лише білий список атрибутів, за замовчуванням: True)

  • sanitize_attributes (bool) – чи очищати атрибути (приймається лише білий список атрибутів, за замовчуванням: True)

  • sanitize_style (bool) – чи очищати атрибути стилів (за замовчуванням: False)

  • strip_style (bool) – чи вилучати атрибути стилю (вилучаються і, відповідно, не очищуються, за замовчуванням: False)

  • strip_classes (bool) – чи вилучати атрибути класів (за замовчуванням: False)

class odoo.fields.Image[source]

Інкапсулює зображення, розширюючи Binary.

Якщо розмір зображення перевищує обмеження max_width/max_height` у пікселях, зображення буде змінено до граничного розміру зі збереженням співвідношення сторін.

Параметри
  • max_width (int) – максимальна ширина зображення (за замовчуванням: 0, без обмежень)

  • max_height (int) – максимальна висота зображення (за замовчуванням: 0, без обмежень)

  • verify_resolution (bool) – чи слід перевіряти роздільну здатність зображення, щоб переконатися, що вона не перевищує максимальну роздільну здатність зображення (за замовчуванням: True). Максимальну роздільну здатність зображення дивіться у odoo.tools.image.ImageProcess (за замовчуванням: 50e6).

Примітка

Якщо max_width/max_height не вказано (або встановлено у 0) і verify_resolution має значення False, вміст поля не буде перевірено взагалі і слід використовувати поле Binary.

class odoo.fields.Monetary[source]

Інкапсулює float, виражений у заданому res_currency.

Десяткова точність і символ валюти беруться з атрибута currency_field.

Параметри

currency_field (str) – назва поля Many2one, що містить res_currency, в якому виражається це грошове поле (за замовчуванням: 'currency_id')

class odoo.fields.Selection[source]

Інкапсулює ексклюзивний вибір між різними значеннями.

Параметри
  • selection (list(tuple(str,str)) or callable or str) – визначає можливі значення для цього поля. Це може бути або список пар (значення, мітка), або метод моделі, або ім’я методу.

  • selection_add (list(tuple(str,str))) – надає розширення вибірки у випадку перевизначеного поля. Це список пар (value, label) або одиночних значень (value,), де одиночні значення повинні з’явитися у перевизначеному виділенні. Нові значення вставляються у порядку, який узгоджується з перевизначеним вибором і цим списком:: selection = [(„a“, „A“), („b“, „B“)] selection_add = [(„c“, „C“), („b“,)] > result = [(„a“, „A“), („c“, „C“), („b“, „B“)]

  • ondelete – забезпечує резервний механізм для будь-якого поля, перевизначеного за допомогою selection_add. Це словник, який зіставляє кожну опцію з selection_add з резервною дією. Ця дія буде застосована до всіх записів, опція selection_add яких має відповідність до неї. Ці дії можуть бути будь-якими з наведених нижче: - „set null“ - за замовчуванням, для всіх записів з цією опцією значенням вибору буде встановлено значення False. - „cascade“ – усі записи з цією опцією буде видалено разом із самою опцією. - „set default“ – для всіх записів з цією опцією буде встановлено значення за замовчуванням визначення поля - <callable> – виклик, першим і єдиним аргументом якого буде набір записів, що містять вказану опцію відбору, для кастомної обробки

Атрибут selection є обов’язковим, окрім випадків related або розширених полів.

class odoo.fields.Text[source]

Дуже схожий на Char, але використовується для довшого вмісту, не має розміру і зазвичай відображається як багаторядкове текстове поле.

Параметри

translate (bool or callable) – увімкнути переклад значень поля; використовувати translate=True для перекладу значень поля в цілому; translate також може бути викликом, так що translate(callback, value) перекладає value, використовуючи callback(term) для отримання перекладу термінів.

Дата(час) поля

Dates і Datetimes є дуже важливими полями в будь-якій бізнес додаток. Їх неправильне використання може створити невидимі, але болючі помилки, цей розділ має на меті надати розробникам Odoo знання, необхідні для уникнення неправильного використання цих полів.

Під час призначення значення полю Date/Datetime дійсні такі параметри:

  • Об’єкт date або datetime.

  • Рядок у відповідному форматі сервера:

    • YYYY-MM-DD для полів Date,

    • YYYY-MM-DD HH:MM:SS для полів Datetime.

  • False або None.

Клас полів Date і Datetime має допоміжні методи для спроб перетворення на сумісний тип:

Example

Для аналізу date/datetimes, що надходять із зовнішніх джерел:

fields.Date.to_date(self._context.get('date_from'))

Рекомендації щодо порівняння Date / Datetime:

  • Поля дати можна лише порівнювати з об’єктами дати.

  • Поля дати й часу можна лише порівнювати з об’єктами дати й часу.

Попередження

Рядки, що представляють dates та datetimes, можна порівнювати між собою, однак результат може не бути очікуваним, оскільки рядок datetime завжди буде більшим за рядок date, тому така практика суворо не рекомендується.

Звичайні операції з dates та datetimes, такі як додавання, віднімання або вибірка початку/кінця періоду, доступні через Date і Datetime. Ці помічники також доступні шляхом імпорту odoo.tools.date_utils.

Примітка

Часові зони

Поля дати й часу зберігаються в базі даних як стовпці timestamp without timezone і зберігаються в часовому поясі UTC. Це задумом, оскільки це робить базу даних Odoo незалежною від часового поясу системи хостинг-сервера. Перетворенням часових поясів повністю керує клієнт.

class odoo.fields.Date[source]

Інкапсулює об’єкт python date.

static add(value, *args, **kwargs)[source]

Повернути суму value і relativedelta.

Параметри
  • value – початкова дата або час.

  • args – позиційні аргументи передавати безпосередньо до relativedelta.

  • kwargs – ключове слово args для передачі безпосередньо до relativedelta.

Повертає

отриману дату/час.

static context_today(record, timestamp=None)[source]

Повертає поточну дату у часовому поясі клієнта у форматі, придатному для полів дати.

Примітка

Цей метод можна використовувати для обчислення значень за замовчуванням.

Параметри
  • record – набір записів, з якого буде отримано часовий пояс.

  • timestamp (datetime) – необов’язкове значення часу, яке буде використовуватися замість поточної дати та часу (це має бути час, звичайні дати не можуть конвертуватися між часовими поясами).

Тип повернення

date

static end_of(value, granularity)[source]

Отримати кінець періоду часу за датою або часом.

Параметри
  • value – початкова дата або час.

  • granularity – Тип періоду в рядку, може бути рік, квартал, місяць, тиждень, день або година.

Повертає

Об’єкт дати/часу, що відповідає початку вказаного періоду.

static start_of(value, granularity)[source]

Об’єкт дати/часу, що відповідає початку вказаного періоду.

Параметри
  • value – початкова дата або час.

  • granularity – тип періоду в рядку, може бути рік, квартал, місяць, тиждень, день або година.

Повертає

об’єкт дати/часу, що відповідає початку вказаного періоду.

static subtract(value, *args, **kwargs)[source]

Повертає різницю між value та relativedelta.

Параметри
  • value – початкова дата або час.

  • args – позиційні аргументи передавати безпосередньо до relativedelta.

  • kwargs – ключове слово args для передачі безпосередньо до relativedelta.

Повертає

отриману дату/час.

static to_date(value)[source]

Спроба перетворити value в об’єкт date.

Попередження

Якщо об’єкт часу даних вказано як значення, його буде перетворено на об’єкт дати, і вся інформація, що стосується часу даних, буде втрачена (HMS, TZ, …).

Параметри

value (str or date or datetime) – значення для перетворення.

Повертає

об’єкт, що представляє value.

Тип повернення

date or None

static to_string(value)[source]

Перетворити об’єкт date або datetime у рядок.

Параметри

value – значення для перетворення.

Повертає

рядок, що представляє value у форматі дати сервера, якщо value має тип datetime, то години, хвилини, секунди, tzinfo буде обрізано.

Тип повернення

str

static today(*args)[source]

Поверніть поточний день у форматі, очікуваному ORM.

Примітка

Ця функція може бути використана для обчислення значень за замовчуванням.

class odoo.fields.Datetime[source]

Інкапсулює об’єкт python datetime.

static add(value, *args, **kwargs)[source]

Повернути суму value і relativedelta.

Параметри
  • value – початкова дата або час.

  • args – позиційні аргументи передавати безпосередньо до relativedelta.

  • kwargs – ключове слово args для передачі безпосередньо до relativedelta.

Повертає

отриману дату/час.

static context_timestamp(record, timestamp)[source]

Повертає задану мітку часу, перетворену в часовий пояс клієнта.

Примітка

Цей метод не призначено для використання як ініціалізатор за замовчуванням, оскільки поля часу даних автоматично конвертуються при відображенні на стороні клієнта. Для значень за замовчуванням слід використовувати now().

Параметри
  • record – набір записів, з якого буде отримано часовий пояс.

  • timestamp (datetime) – значення місцевого часу (виражене в UTC) для перетворення в часовий пояс клієнта.

Повертає

мітку часу перетворено на час з урахуванням часового поясу у контекстному часовому поясі.

Тип повернення

datetime

static end_of(value, granularity)[source]

Отримати кінець періоду часу за датою або часом.

Параметри
  • value – початкова дата або час.

  • granularity – Тип періоду в рядку, може бути рік, квартал, місяць, тиждень, день або година.

Повертає

Об’єкт дати/часу, що відповідає початку вказаного періоду.

static now(*args)[source]

Повертає поточний день і час у форматі, який очікує ORM.

Примітка

Ця функція може бути використана для обчислення значень за замовчуванням.

static start_of(value, granularity)[source]

Об’єкт дати/часу, що відповідає початку вказаного періоду.

Параметри
  • value – початкова дата або час.

  • granularity – тип періоду в рядку, може бути рік, квартал, місяць, тиждень, день або година.

Повертає

об’єкт дати/часу, що відповідає початку вказаного періоду.

static subtract(value, *args, **kwargs)[source]

Повертає різницю між value та relativedelta.

Параметри
  • value – початкова дата або час.

  • args – позиційні аргументи передавати безпосередньо до relativedelta.

  • kwargs – ключове слово args для передачі безпосередньо до relativedelta.

Повертає

отриману дату/час.

static to_datetime(value)[source]

Перетворити ORM value у значення datetime`.

Параметри

value (str or date or datetime) – значення для перетворення.

Повертає

об’єкт, що представляє value.

Тип повернення

datetime or None

static to_string(value)[source]

Перетворити об’єкт datetime або date у рядок.

Параметри

value (datetime or date) – значення для перетворення.

Повертає

рядок, що представляє value у форматі дата-час сервера, якщо value має тип date, то часовою частиною буде північ (00:00:00).

Тип повернення

str

static today(*args)[source]

Повертає поточний день, опівночі (00:00:00).

Реляційні поля

class odoo.fields.Many2one[source]

Значенням такого поля є набір записів розміром 0 (жодного запису) або 1 (один запис).

Параметри
  • comodel_name (str) – назва цільової моделі Обов'язкова, за винятком пов’язаних або розширених полів.

  • domain – необов’язковий домен для встановлення значень кандидатів на стороні клієнта (домен або рядок)

  • context (dict) – необов’язковий контекст для використання на стороні клієнта під час роботи з цим полем

  • ondelete (str) – що робити при видаленні запису, на який є посилання; можливі значення 'set null', 'restrict', 'cascade'

  • auto_join (bool) – чи створюються об’єднання при пошуку за цим полем (за замовчуванням: False)

  • delegate (bool) – встановлює значення True, щоб зробити поля цільової моделі доступними з поточної моделі (відповідає _inherits)

  • check_company (bool) – Позначте поле для перевірки у _check_company(). Додайте домен компанії за замовчуванням залежно від атрибутів поля.

class odoo.fields.One2many[source]

Поле типу one2many; значенням такого поля є набір записів усіх записів у comodel_name таких, що поле inverse_name дорівнює поточному запису.

Параметри
  • comodel_name (str) – назва цільової моделі

  • inverse_name (str) – назва зворотного поля Many2one в comodel_name

  • domain – необов’язковий домен для встановлення значень кандидатів на стороні клієнта (домен або рядок)

  • context (dict) – необов’язковий контекст для використання на стороні клієнта під час роботи з цим полем

  • auto_join (bool) – чи створюються об’єднання при пошуку за цим полем (за замовчуванням: False)

  • limit (int) – необов’язковий ліміт для використання при зчитуванні

Атрибути comodel_name та inverse_name є обов’язковими, окрім випадків пов’язаних полів або розширень полів.

class odoo.fields.Many2many[source]

Поле many2many; значенням такого поля є набір записів.

Параметри
  • comodel_name – назва цільової моделі (рядок) обов’язкова, за винятком випадку пов’язаних або розширених полів

  • relation (str) – необов’язкова назва таблиці, яка зберігає відношення в базі даних

  • column1 (str) – необов’язкова назва стовпця, що посилається на «ці» записи в таблиці relation

  • column2 (str) – необов’язкова назва стовпця, що посилається на «ті» записи в таблиці relation

Атрибути relation, column1 та column2 є необов’язковими. Якщо їх не задано, імена автоматично генеруються з імен моделей, якщо model_name та comodel_name відрізняються!

Зауважте, що наявність декількох полів з неявними параметрами зв’язку на даній моделі з тією самою комоделлю не сприймається ORM, оскільки ці поля будуть використовувати ту саму таблицю. ORM не дозволяє двом полям типу many2many використовувати однакові параметри зв’язку, за винятком випадків, коли

  • в обох полях використовується однакова модель, комодель, і параметри зв’язку є явними; або

  • хоча б одне поле належить моделі з _auto = False.

Параметри
  • domain – необов’язковий домен для встановлення значень кандидатів на стороні клієнта (домен або рядок)

  • context (dict) – необов’язковий контекст для використання на стороні клієнта під час роботи з цим полем

  • check_company (bool) – Позначте поле для перевірки у _check_company(). Додайте домен компанії за замовчуванням залежно від атрибутів поля.

  • limit (int) – необов’язковий ліміт для використання при зчитуванні

Псевдореляційні поля

class odoo.fields.Reference[source]

Псевдореляційне поле (немає FK в базі даних).

Значення поля зберігається у базі даних у вигляді рядка string за зразком "res_model,res_id".

class odoo.fields.Many2oneReference[source]

Псевдореляційне поле (немає FK в базі даних).

Значення поля зберігається в базі даних як integer id.

На відміну від полів Посилання, модель має бути вказана у полі Char, назва якого має бути вказана в атрибуті model_field для поточного поля Many2oneReference.

Параметри

model_field (str) – назва Char, де зберігається назва моделі.

Обчислювані поля

Поля можна обчислити (замість читання безпосередньо з бази даних) за допомогою параметра compute. Він повинен призначити обчислене значення полю. Якщо він використовує значення інших полів, він має вказати ці поля за допомогою depends().

from odoo import api
total = fields.Float(compute='_compute_total')

@api.depends('value', 'tax')
def _compute_total(self):
    for record in self:
        record.total = record.value + record.value * record.tax
  • залежності можуть бути виділені пунктиром, якщо використовуються підполя:

    @api.depends('line_ids.value')
    def _compute_total(self):
        for record in self:
            record.total = sum(line.value for line in record.line_ids)
    
  • обчислені поля не зберігаються за замовчуванням, вони обчислюються та повертаються за запитом. Встановлення store=True зберігатиме їх у базі даних і автоматично вмикатиме пошук.

  • пошук у обчисленому полі також можна ввімкнути, встановивши параметр search. Значенням є назва методу, що повертає Пошук доменів.

    upper_name = field.Char(compute='_compute_upper', search='_search_upper')
    
    def _search_upper(self, operator, value):
        if operator == 'like':
            operator = 'ilike'
        return [('name', operator, value)]
    

    Метод пошуку викликається під час обробки доменів перед виконанням фактичного пошуку в моделі. Він має повертати домен, еквівалентний умові: значення оператора поля.

  • За замовчуванням обчислені поля доступні лише для читання. Щоб дозволити встановлювати значення в обчисленому полі, використовуйте параметр inverse. Це назва функції, яка повертає обчислення та встановлює відповідні поля:

    document = fields.Char(compute='_get_document', inverse='_set_document')
    
    def _get_document(self):
        for record in self:
            with open(record.get_document_path) as f:
                record.document = f.read()
    def _set_document(self):
        for record in self:
            if not record.document: continue
            with open(record.get_document_path()) as f:
                f.write(record.document)
    
  • кілька полів можна обчислювати одночасно одним і тим же методом, просто використовуйте той самий метод для всіх полів і встановіть усі:

    discount_value = fields.Float(compute='_apply_discount')
    total = fields.Float(compute='_apply_discount')
    
    @api.depends('value', 'discount')
    def _apply_discount(self):
        for record in self:
            # compute actual discount from discount percentage
            discount = record.value * record.discount
            record.discount_value = discount
            record.total = record.value - discount
    

Попередження

Хоча можна використовувати той самий метод обчислення для кількох полів, не рекомендується робити те саме для зворотного методу.

Під час обчислення інверсії всі поля, які використовують згадану інверсію, захищені, тобто їх неможливо обчислити, навіть якщо їх значення немає в кеші.

Якщо здійснюється доступ до будь-якого з цих полів, а його значення немає в кеші, ORM просто поверне значення за замовчуванням False для цих полів. Це означає, що значення інверсних полів (окрім того, яке запускає інверсний метод) може не давати правильне значення, і це, ймовірно, порушить очікувану поведінку інверсного методу.

Автоматичні поля

odoo.fields.id

Ідентифікатор поле

Якщо довжина поточного набору записів дорівнює 1, поверніть ідентифікатор унікального запису в ньому.

Інакше вивести помилку.

Поля журналу доступу

Ці поля встановлюються та оновлюються автоматично, якщо _log_access увімкнено. Його можна вимкнути, щоб уникнути створення або оновлення тих полів у таблицях, для яких вони не є корисними.

За замовчуванням _log_access має те саме значення, що й _auto

odoo.fields.create_date

Зберігає дату створення запису, Datetime

odoo.fields.create_uid

Зберігає хто створив запис, Many2one до res.users.

odoo.fields.write_date

Зберігає час останнього оновлення запису, Datetime

odoo.fields.write_uid

Зберігає, хто останнім оновив запис, Many2one до res.users.

Попередження

_log_access має бути включений на TransientModel.

Зарезервовані назви полів

Кілька назв полів зарезервовано для попередньо визначеної поведінки, крім автоматизованих полів. Вони повинні бути визначені в моделі, коли потрібна відповідна поведінка:

odoo.fields.name

значення за замовчуванням для _rec_name, яке використовується для відображення записів у контексті, де потрібне репрезентативне «іменування».

Char

odoo.fields.active

перемикає загальну видимість запису, якщо active встановлено на False, запис невидимий у більшості пошуків і списків.

Boolean

odoo.fields.state

етапи життєвого циклу об’єкта, які використовуються атрибутом states на fields.

Selection

odoo.fields.parent_id

default_value _parent_name, що використовується для організації записів у структурі дерева та дозволяє оператори child_of і parent_of у доменах.

Many2one

odoo.fields.parent_path

Коли _parent_store має значення True, використовується для збереження значення, що відображає структуру дерева _parent_name, і для оптимізації операторів child_of і parent_of у домени пошуку. Для належної роботи він має бути оголошений за допомогою index=True.

Char

odoo.fields.company_id

Основна назва поля, яке використовується для поведінки мульти-компаній Odoo.

Використовується :meth:~odoo.models._check_company для перевірки узгодженості мульти-компаній. Визначає, чи є запис спільною для компаній (без значення) чи доступний лише користувачам певної компанії.

Many2one :type: res_company

Набори записів

Взаємодія з моделями та записами здійснюється через набори записів, упорядковану колекцію записів однієї моделі.

Попередження

На відміну від назви, наразі набори записів можуть містити дублікати. Це може змінитися в майбутньому.

Методи, визначені в моделі, виконуються в наборі записів, а їх self є набором записів:

class AModel(models.Model):
    _name = 'a.model'
    def a_method(self):
        # self can be anything between 0 records and all records in the
        # database
        self.do_operation()

Ітерація набору записів дасть нові набори з одного запису («singletons»), подібно до того, як ітерація рядка Python дає рядки з окремих символів:

def do_operation(self):
    print(self) # => a.model(1, 2, 3, 4, 5)
    for record in self:
        print(record) # => a.model(1), then a.model(2), then a.model(3), ...

Доступ до поля

Набори записів забезпечують інтерфейс «Активний запис»: поля моделі можна читати та записувати безпосередньо із запису як атрибути.

Примітка

Під час доступу до нереляційних полів у наборі записів із потенційно кількох записів використовуйте mapped():

total_qty = sum(self.mapped('qty'))

До значень полів також можна отримати доступ, як до елементів dict, що елегантніше та безпечніше, ніж getattr() для динамічних назв полів. Встановлення значення поля запускає оновлення бази даних:

>>> record.name
Example Name
>>> record.company_id.name
Company Name
>>> record.name = "Bob"
>>> field = "name"
>>> record[field]
Bob

Попередження

Спроба прочитати поле в кількох записах призведе до помилки для нереляційних полів.

Доступ до реляційного поля (Many2one, One2many, Many2many) завжди повертає набір записів, порожній, якщо поле не встановлено.

Кешування записів і попередня вибірка

Odoo підтримує кеш-пам’ять для полів записів, тому не кожен доступ до поля видає запит бази даних, що було б жахливим для продуктивності. Наведений нижче приклад запитує базу даних лише для першого оператора:

record.name             # first access reads value from database
record.name             # second access gets value from cache

Щоб уникнути читання одного поля в одному записі за раз, Odoo попередньо вибирає записи та поля, дотримуючись певних евристик, щоб отримати хорошу продуктивність. Після того, як поле має бути прочитано в заданому записі, ORM фактично зчитує це поле у більшому наборі записів і зберігає повернуті значення в кеші для подальшого використання. Попередньо вибраний набір записів зазвичай є набором записів, з якого запис надходить ітерацією. Крім того, усі прості збережені поля (логічне, ціле, float, char, text, date, datetime, selection, many2one) вибираються в цілому; вони відповідають стовпцям таблиці моделі та ефективно витягуються в одному запиті.

Розглянемо наступний приклад, де partners - це набір із 1000 записів. Без попередньої вибірки цикл зробить 2000 запитів до бази даних. З попередньою вибіркою виконується лише один запит:

for partner in partners:
    print partner.name          # first pass prefetches 'name' and 'lang'
                                # (and other fields) on all 'partners'
    print partner.lang

Попередня вибірка також працює з вторинними записами: коли зчитуються реляційні поля, їхні значення (які є записами) підписуються для майбутньої попередньої вибірки. Доступ до одного з цих вторинних записів попередньо завантажує всі вторинні записи з тієї самої моделі. Таким чином у наведеному нижче прикладі створюються лише два запити, один для партнерів і один для країн:

countries = set()
for partner in partners:
    country = partner.country_id        # first pass prefetches all partners
    countries.add(country.name)         # first pass prefetches all countries

Декоратори методів

Модуль Odoo API визначає середовища Odoo та декоратори методів.

odoo.api.autovacuum(method)[source]

Прикрасьте метод так, щоб він викликався щоденним завданням cron прибирання (модель ir.autovacuum). Зазвичай це використовується для завдань на кшталт збирання сміття, які не заслуговують на окреме завдання cron.

odoo.api.constrains(*args)[source]

Прикрасьте перевірку обмежень.

Кожен аргумент має бути назвою поля, яке використовується під час перевірки:

@api.constrains('name', 'description')
def _check_description(self):
    for record in self:
        if record.name == record.description:
            raise ValidationError("Fields name and description must be different")

Викликається для записів, у яких одне з названих полів було змінено.

Має викликати ValidationError, якщо перевірка не вдалася.

Попередження

@constrains підтримує лише прості назви полів, назви з крапками (поля реляційних полів, наприклад partner_id.customer) не підтримуються та ігноруватимуться.

@constrains запускатиметься, лише якщо оголошені поля в декорованому методі включено до виклику create або write. Це означає, що поля, яких немає в поданні, не викликатимуть виклик під час створення запису. Перевизначення create необхідне, щоб переконатися, що обмеження завжди запускатиметься (наприклад, щоб перевірити відсутність значення).

odoo.api.depends(*args)[source]

Повертає декоратор, який визначає залежності полів методу «обчислення» (для полів функцій нового стилю). Кожен аргумент має бути рядком, який складається з послідовності назв полів, розділених крапками:

pname = fields.Char(compute='_compute_pname')

@api.depends('partner_id.name', 'partner_id.is_company')
def _compute_pname(self):
    for record in self:
        if record.partner_id.is_company:
            record.pname = (record.partner_id.name or "").upper()
        else:
            record.pname = record.partner_id.name

Можна також передати одну функцію як аргумент. У цьому випадку залежності задаються шляхом виклику функції з моделлю поля.

odoo.api.depends_context(*args)[source]

Повертає декоратор, який визначає контекстні залежності незбереженого «обчислювального» методу. Кожен аргумент є ключем у словнику контексту:

price = fields.Float(compute='_compute_product_price')

@api.depends_context('pricelist')
def _compute_product_price(self):
    for product in self:
        if product.env.context.get('pricelist'):
            pricelist = self.env['product.pricelist'].browse(product.env.context['pricelist'])
        else:
            pricelist = self.env['product.pricelist'].get_default_pricelist()
        product.price = pricelist.get_products_price(product).get(product.id, 0.0)

Усі залежності мають бути хешованими. Наступні ключі мають спеціальну підтримку:

  • company (значення в контексті або поточний ідентифікатор компанії),

  • uid (поточний id користувача та прапор суперкористувача),

  • active_test (значення в env.context або значення в field.context).

odoo.api.model(method)[source]

Прикрасьте метод у стилі запису, де self є набором записів, але його вміст нерелевантний, має значення лише модель. Такий спосіб:

@api.model
def method(self, args):
    ...
odoo.api.model_create_multi(method)[source]

Прикрасьте метод, який приймає список словників і створює кілька записів. Метод може бути викликаний або з одним dict, або зі списком dicts:

record = model.create(vals)
records = model.create([vals, ...])
odoo.api.onchange(*args)[source]

Повертає декоратор, щоб прикрасити метод onchange для заданих полів.

У представленнях форми, де з’являється поле, метод буде викликано, коли одне з заданих полів буде змінено. Метод викликається для псевдозапису, який містить значення, присутні у формі. Призначення полів у цьому записі автоматично надсилаються назад клієнту.

Кожен аргумент має бути назвою поля:

@api.onchange('partner_id')
def _onchange_partner(self):
    self.message = "Dear %s" % (self.partner_id.name or "")
return {
    'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},
}

Якщо для типу встановлено сповіщення, попередження відображатиметься в сповіщенні. Інакше він відображатиметься у діалоговому вікні за замовчуванням.

Попередження

@onchange підтримує лише прості назви полів, крапкові імена (поля реляційних полів, наприклад, partner_id.tz) не підтримуються і будуть проігноровані

Небезпека

Оскільки @onchange повертає набір псевдозаписів, виклик будь-якого з методів CRUD (create(), read(), write(), unlink()) для цього набору записів є невизначеною поведінкою, оскільки вони потенційно ще не існують в базі даних.

Замість цього просто встановіть поле запису, як показано у прикладі вище, або викличте метод update().

Попередження

Поле one2many або many2many не може модифікувати себе через onchange. Це обмеження веб-клієнта - див. #2693.

odoo.api.returns(model, downgrade=None, upgrade=None)[source]

Повертає декоратор для методів, які повертають екземпляри model.

Параметри
  • model – назва моделі або 'self для поточної моделі

  • downgrade – функція downgrade(self, value, *args, **kwargs) для перетворення value у стилі запису на вивід у традиційному стилі

  • upgrade – функцію upgrade(self, value, *args, **kwargs) для перетворення value у традиційному стилі у вивід у стилі запису

Аргументи self, *args і **kwargs - це ті, що передаються в метод у стилі запису.

Декоратор адаптує вивід методу до стилю api: id, ids або False для традиційного стилю, і recordset для стилю записів:

@model
@returns('res.partner')
def find_partner(self, arg):
    ...     # return some record

# output depends on call style: traditional vs record style
partner_id = model.find_partner(cr, uid, arg, context=context)

# recs = model.browse(cr, uid, ids, context)
partner_record = recs.find_partner(arg)

Зверніть увагу, що декорований метод повинен задовольняти цій умові.

Ці декоратори автоматично успадковуються: метод, який перевизначає декорований існуючий метод, буде декорований тим самим @returns(model).

Середовище

У Environment зберігаються різні контекстні дані, що використовуються ORM: курсор бази даних (для запитів до бази даних), поточний користувач (для перевірки прав доступу) та поточний контекст (для зберігання довільних метаданих). Середовище також зберігає кеш.

Всі набори записів мають оточення, яке є незмінним, до нього можна отримати доступ за допомогою env:

  • поточний користувач (user)

  • курсор (cr)

  • прапор суперкористувача (su)

  • або контекст (context)

>>> records.env
<Environment object ...>
>>> records.env.user
res.user(3)
>>> records.env.cr
<Cursor object ...)

При створенні набору записів з іншого набору записів, оточення успадковується. Оточення можна використати для отримання порожнього набору записів в іншій моделі, а також для запиту до цієї моделі:

>>> self.env['res.partner']
res.partner()
>>> self.env['res.partner'].search([['is_company', '=', True], ['customer', '=', True]])
res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)
Environment.ref(xml_id, raise_if_not_found=True)[source]

Повернути запис, що відповідає заданому xml_id.

Environment.lang

Повернути поточний код мови.

Тип повернення

str

Environment.user

Return the current user (as an instance).

Тип повернення

res_users

Environment.company

Return the current company (as an instance).

If not specified in the context (allowed_company_ids), fallback on current user main company.

Викликає

AccessError – invalid or unauthorized allowed_company_ids context key content.

Повертає

current company (default=`self.user.company_id`)

Тип повернення

res.company

Попередження

No sanity checks applied in sudo mode ! When in sudo mode, a user can access any company, even if not in his allowed companies.

This allows to trigger inter-company modifications, even if the current user doesn’t have access to the targeted company.

Environment.companies

Return a recordset of the enabled companies by the user.

If not specified in the context(allowed_company_ids), fallback on current user companies.

Викликає

AccessError – invalid or unauthorized allowed_company_ids context key content.

Повертає

current companies (default=`self.user.company_ids`)

Тип повернення

res.company

Попередження

No sanity checks applied in sudo mode ! When in sudo mode, a user can access any company, even if not in his allowed companies.

This allows to trigger inter-company modifications, even if the current user doesn’t have access to the targeted company.

Зміна середовища

Model.with_context([context][, **overrides]) records[source]

Returns a new version of this recordset attached to an extended context.

The extended context is either the provided context in which overrides are merged or the current context in which overrides are merged e.g.:

# current context is {'key1': True}
r2 = records.with_context({}, key2=True)
# -> r2._context is {'key2': True}
r2 = records.with_context(key2=True)
# -> r2._context is {'key1': True, 'key2': True}
Model.with_user(user)[source]

Return a new version of this recordset attached to the given user, in non-superuser mode, unless user is the superuser (by convention, the superuser is always in superuser mode.)

Model.with_company(company)[source]

Return a new version of this recordset with a modified context, such that:

result.env.company = company
result.env.companies = self.env.companies | company
Параметри

company (res_company or int) – головна компанія нового середовища.

Попередження

When using an unauthorized company for current user, accessing the company(ies) on the environment may trigger an AccessError if not done in a sudoed environment.

Model.with_env(env)[source]

Return a new version of this recordset attached to the provided environment.

Параметри

env (Environment) –

Попередження

The new environment will not benefit from the current environment’s data cache, so later data access may incur extra delays while re-fetching from the database. The returned recordset has the same prefetch object as self.

Model.sudo([flag=True])[source]

Returns a new version of this recordset with superuser mode enabled or disabled, depending on flag. The superuser mode does not change the current user, and simply bypasses access rights checks.

Попередження

Using sudo could cause data access to cross the boundaries of record rules, possibly mixing records that are meant to be isolated (e.g. records from different companies in multi-company environments).

It may lead to un-intuitive results in methods which select one record among many - for example getting the default company, or selecting a Bill of Materials.

Примітка

Because the record rules and access control will have to be re-evaluated, the new recordset will not benefit from the current environment’s data cache, so later data access may incur extra delays while re-fetching from the database. The returned recordset has the same prefetch object as self.

Виконання SQL

Атрибут cr в середовищах є курсором для поточної транзакції бази даних і дозволяє безпосередньо виконувати SQL або для запитів, які важко виразити за допомогою ORM (наприклад, складні об’єднання), або для продуктивності причини:

self.env.cr.execute("some_sql", params)

Оскільки моделі використовують той самий курсор, а Environment містить різні кеші, ці кеші мають бути визнані недійсними під час зміни бази даних у необробленому SQL, інакше подальше використання моделей може стати неузгодженим. Необхідно очищати кеші під час використання CREATE, UPDATE або DELETE у SQL, але не SELECT (який просто читає базу даних).

Примітка

Clearing caches can be performed using the invalidate_cache() method.

Model.invalidate_cache(fnames=None, ids=None)[source]

Invalidate the record caches after some records have been modified. If both fnames and ids are None, the whole cache is cleared.

Параметри
  • fnames – the list of modified fields, or None for all fields

  • ids – the list of modified record ids, or None for all

Попередження

Executing raw SQL bypasses the ORM, and by consequent, Odoo security rules. Please make sure your queries are sanitized when using user input and prefer using ORM utilities if you don’t really need to use SQL queries.

Поширені методи ORM

Створити/оновити

Model.create(vals_list) records[source]

Створює нові записи для моделі.

The new records are initialized using the values from the list of dicts vals_list, and if necessary those from default_get().

Параметри

vals_list (list) –

делегування деяких полів моделі записам, які вона містить:

[{'field_name': field_value, ...}, ...]

For backward compatibility, vals_list may be a dictionary. It is treated as a singleton list [vals], and a single record is returned.

see write() for details

Повертає

the created records

Викликає
  • AccessError

    • if user has no create rights on the requested object

    • if user tries to bypass access rules for create on the requested object

  • ValidationError – if user tries to enter invalid value for a field that is not in selection

  • UserError – if a loop would be created in a hierarchy of objects a result of the operation (such as setting an object as its own parent)

Model.copy(default=None)[source]

Duplicate record self updating it with default values

Параметри

default (dict) – dictionary of field values to override in the original values of the copied record, e.g: {'field_name': overridden_value, ...}

Повертає

new record

Model.default_get(fields_list) default_values[source]

Return default values for the fields in fields_list. Default values are determined by the context, user defaults, and the model itself.

Параметри

fields_list (list) – names of field whose default is requested

Повертає

словник, що зіставляє назви полів із відповідними значеннями за замовчуванням, якщо вони мають значення за замовчуванням.

Тип повернення

dict

Примітка

Unrequested defaults won’t be considered, there is no need to return a value for fields whose names are not in fields_list.

Model.name_create(name) record[source]

Create a new record by calling create() with only one value provided: the display name of the new record.

The new record will be initialized with any default values applicable to this model, or provided through the context. The usual behavior of create() applies.

Параметри

name – display name of the record to create

Тип повернення

tuple

Повертає

the name_get() pair value of the created record

Model.write(vals)[source]

Updates all records in the current set with the provided values.

Параметри

vals (dict) – поля для оновлення та значення для них, наприклад:: {„foo“: 1, „bar“: «Qux»} встановить поле foo на 1, а поле bar` ` до ``"Qux", якщо вони дійсні (інакше це викличе помилку).

Викликає
  • AccessError

    • якщо користувач не має прав на запис запитуваного об’єкта

    • якщо користувач намагається обійти правила доступу для запису на запитуваний об’єкт

  • ValidationError – if user tries to enter invalid value for a field that is not in selection

  • UserError – if a loop would be created in a hierarchy of objects a result of the operation (such as setting an object as its own parent)

  • Для числових полів (Integer, Float) значення має бути відповідного типу

  • Для Boolean значення має бути bool

  • Для Selection значення має відповідати значенням вибору (зазвичай str, іноді int)

  • Для Many2one значення має бути ідентифікатором бази даних запису, який потрібно встановити

  • Інші нереляційні поля використовують рядок для значення

    Небезпека

    з міркувань історії та сумісності поля Date і Datetime використовують рядки як значення (записані та прочитані), а не date або datetime. Ці рядки дат є лише UTC і відформатовані відповідно до odoo.tools.misc.DEFAULT_SERVER_DATE_FORMAT і odoo.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT

  • One2many і Many2many використовують спеціальний формат «команд» для маніпулювання набором записів, що зберігаються в/пов’язаних із полем.

    Цей формат являє собою список триплетів, що виконуються послідовно, де кожен триплет є командою для виконання на наборі записів. Не всі команди застосовуються в усіх ситуаціях. Можливі команди:

    (0, 0, values)

    додає новий запис, створений із наданого значення dict.

    (1, id, values)

    оновлює наявний запис ідентифікатора id значеннями в values. Не можна використовувати в create().

    (2, id, 0)

    видаляє запис id id із набору, а потім видаляє його (з бази даних). Не можна використовувати в create().

    (3, id, 0)

    видаляє запис ідентифікатора id із набору, але не видаляє його. Не можна використовувати в create().

    (4, id, 0)

    додає наявний запис ідентифікатора id до набору.

    (5, 0, 0)

    видаляє всі записи з набору, еквівалентно використанню команди 3 для кожного запису явно. Не можна використовувати в create().

    (6, 0, ids)

    замінює всі наявні записи в наборі списком ids, еквівалентно використанню команди 5, після якої йде команда 4 для кожного id в ids.

Model.flush(fnames=None, records=None)[source]

Обробити всі незавершені обчислення (на всіх моделях) і очистити всі незавершені оновлення бази даних.

Параметри
  • (list<str>) (fnames) – список назв полів для очищення. Якщо задано, обмежити обробку заданими полями поточної моделі.

  • (Model) (records) – якщо задано (разом із fnames), обмежити обробку вказаними записами.

Пошук/Читання

Model.browse([ids]) records[source]

Повертає набір записів для ідентифікаторів, наданих як параметр у поточному середовищі.

self.browse([7, 18, 12])
res.partner(7, 18, 12)
Параметри

ids (int or list(int) or None) – id(s)

Повертає

recordset

Model.search(args[, offset=0][, limit=None][, order=None][, count=False])[source]

Шукає записи на основі args домен пошуку.

Параметри
  • argsДомен пошуку. Використовуйте порожній список, щоб зіставити всі записи.

  • offset (int) – кількість результатів для ігнорування (за замовчуванням: немає)

  • limit (int) – максимальна кількість записів для повернення (за замовчуванням: усі)

  • order (str) – рядок сортування

  • count (bool) – якщо True, підраховує та повертає лише кількість відповідних записів (за замовчуванням: False)

Повертає

щонайбільше limit записів, що відповідають критеріям пошуку

Викликає

AccessError

  • якщо користувач намагається обійти правила доступу для читання запитуваного об’єкта.

Model.search_count(args) int[source]

Повертає кількість записів у поточній моделі, які відповідають наданому домену.

Шукайте записи, які мають відображувану назву, що відповідає даному шаблону name у порівнянні з даним operator, а також відповідає додатковому домену пошуку (args).

Це використовується, наприклад, для надання пропозицій на основі часткового значення для реляційного поля. Іноді розглядається як зворотна функція name_get(), але це не гарантовано.

Цей метод еквівалентний виклику search() із доменом пошуку на основі display_name, а потім name_get() у результаті пошуку.

Параметри
  • name (str) – зразок назви для відповідності

  • args (list) – додатковий домен пошуку (синтаксис див. у search()), вказуючи додаткові обмеження

  • operator (str) – оператор домену для відповідності name, наприклад 'like' або '='.

  • limit (int) – опціональна максимальна кількість записів для повернення

Тип повернення

list

Повертає

список пар (id, text_repr) для всіх відповідних записів.

Model.read([fields])[source]

Читає запитані поля для записів у self, метод низького рівня/RPC. У коді Python надавайте перевагу browse().

Параметри

fields – список назв полів для повернення (за замовчуванням усі поля)

Повертає

список словників, що відображають назви полів на їхні значення, з одним словником на запис

Викликає

AccessError – якщо користувач не має прав на читання деяких із наведених записів

Model.read_group(domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True)[source]

Отримайте список записів у режимі перегляду списку, згрупованих за заданими полями groupby.

Параметри
  • domain (list) – Домен пошуку. Використовуйте порожній список, щоб зіставити всі записи.

  • fields (list) – список полів, присутніх у списку, указаному на об’єкті. Кожен елемент є або „field“ (назва поля, з використанням агрегації за замовчуванням), або „field:agg“ (агрегованого поля з функцією агрегації „agg“), або „name:agg(field)“ (агрегованого поля з „agg“ і повернути його як „name“). Можливими функціями агрегації є ті, що надаються PostgreSQL (https://www.postgresql.org/docs/current/static/functions-aggregate.html) і „count_distinct“, з очікуваним значенням.

  • groupby (list) – список груп за описами, за якими будуть згруповані записи. Опис groupby - це або поле (тоді воно буде згруповано за цим полем), або рядок „field:groupby_function“. Наразі підтримуються лише функції „day“, „week“, „month“, „quarter“ або „year“,, і вони мають сенс лише для полів дати/часу.

  • offset (int) – необов’язкова кількість записів, які потрібно пропустити

  • limit (int) – опціональна максимальна кількість записів для повернення

  • orderby (str) – необов’язкова специфікація order by, щоб змінити природне впорядкування груп, див. також search() (наразі підтримується лише для полів many2one)

  • lazy (bool) – якщо true, результати групуються лише за першим groupby, а решта groupby поміщаються в ключ __context. Якщо false, усі groupby виконуються за один виклик.

Повертає

список словників (один словник для кожного запису), що містить: * значення полів, згрупованих за полями в аргументі groupby * __domain: список кортежів із зазначенням критеріїв пошуку * __context: словник з аргументом, таким як groupby

Тип повернення

[{„field_name_1“: value, …]

Викликає

AccessError

  • якщо користувач не має прав на читання запитуваного об’єкта

  • якщо користувач намагається обійти правила доступу для читання запитуваного об’єкта

Поля/Представлення

Model.fields_get([fields][, attributes])[source]

Повернути визначення кожного поля.

Повернене значення є словником (індексованим за назвою поля) словників. Включено поля _inherits’d. Атрибути string, help і selection (якщо є) перекладаються.

Параметри
  • allfields – список полів для документування, якщо всі вони порожні або не надані

  • attributes – список полів для документування, якщо всі вони порожні або не надані

Model.fields_view_get([view_id | view_type='form'])[source]

Отримайте детальний склад запитуваного представлення, як-от поля, модель, архітектура представлення

Параметри
  • view_id (int) – id представлення або None

  • view_type (str) – тип представлення для повернення, якщо view_id дорівнює None („form“, „tree“, …)

  • toolbar (bool) – true для включення контекстних дій

  • submenu – deprecated

Повертає

склад запитаного представлення (включаючи успадковані представлення та розширення)

Тип повернення

dict

Викликає
  • AttributeError

    • якщо успадковане подання має невідому позицію для роботи, крім „before“, „after“, „inside“, „replace“

    • якщо в батьківському представленні знайдено тег, відмінний від „position“

  • Invalid ArchitectureError – якщо в структурі визначено тип представленні, відмінний від форми, списку, календаря, пошуку тощо

Пошук доменів

Домен - це список критеріїв, кожен критерій - це трійка (або список, або кортеж) (field_name, operator, value), де:

  • field_name (str)

    назва поля поточної моделі або обхід зв’язку через Many2one з використанням крапкової нотації, наприклад. 'street' або 'partner_id.country'

  • operator (str)

    оператор, який використовується для порівняння field_name із value. Допустимі оператори:

    =

    дорівнює

    !=

    не дорівнює

    >

    більше ніж

    >=

    більше або дорівнює

    <

    менше ніж

    <=

    менше або дорівнює

    =?

    не встановлено або дорівнює (повертає істину, якщо value або None або False, інакше поводиться як =)

    =like

    відповідає field_name шаблону value. Підкреслення _ у шаблоні означає (відповідає) будь-якому окремому символу; знак відсотка % відповідає будь-якому рядку з нуля або більше символів.

    like

    співпадає field_name шаблону %value%. Подібно до =like, але value обертає „%“ перед пошуком відповідності

    not like

    не відповідає шаблону %value%

    ilike

    без урахування регістру like

    not ilike

    без урахування регістру not like

    =ilike

    без урахування регістру =like

    in

    дорівнює будь-якому з елементів із value, value має бути списком елементів

    not in

    не дорівнює всім елементам із value

    child_of

    є дочірнім (нащадком) запису value (значення може бути або одним елементом, або списком елементів).

    Враховує семантику моделі (тобто після поля зв’язку, названого _parent_name).

    parent_of

    є батьківським (висхідним) запису value (значення може бути як одним елементом, так і списком елементів).

    Враховує семантику моделі (тобто після поля зв’язку, названого _parent_name).

  • value

    тип змінної, має бути порівнянним (через operator) з іменованим полем.

Критерії домену можна комбінувати за допомогою логічних операторів у формі prefix:

'&'

логічне AND, операція за замовчуванням для комбінування наступних критеріїв. Arity 2 (використовує наступні 2 критерії або комбінації).

'|'

логічне OR, арність 2.

'!'

логічне NOT, арність 1.

Примітка

Здебільшого для заперечення комбінацій критеріїв. Окремий критерій, як правило, має негативну форму (наприклад, = -> !=, < -> >=), що простіше, ніж заперечення позитивного .

Example

Для пошуку партнерів на ім’я ABC з Бельгії чи Німеччини, мова яких не є англійською:

[('name','=','ABC'),
 ('language.code','!=','en_US'),
 '|',('country_id.code','=','be'),
     ('country_id.code','=','de')]

Цей домен інтерпретується як:

    (name is 'ABC')
AND (language is NOT english)
AND (country is Belgium OR Germany)

Запис (набір) інформації

Model.ids

Повертає список фактичних ідентифікаторів записів, які відповідають self.

odoo.models.env

Повертає середовище заданого набору записів.

тип

Environment

Model.exists() records[source]

Повертає підмножину існуючих записів у self і позначає видалені записи як такі в кеші. Його можна використовувати як тест на записи:

if record.exists():
    ...

Згідно з умовами, нові записи повертаються як існуючі.

Model.ensure_one()[source]

Переконайтеся, що поточний recorset містить один запис.

Викликає

odoo.exceptions.ValueErrorlen(self) != 1

Model.name_get() [id, name, ...][source]

Повертає текстове представлення для записів у self. За замовчуванням це значення поля display_name.

Повертає

список пар (id, text_repr) для кожного запису

Тип повернення

list(tuple)

Model.get_metadata()[source]

Повернути деякі метадані про дані записи.

Повертає

список словників власності для кожного запитуваного запису

Тип повернення

список словників із такими ключами: * id: ідентифікатор об’єкта * create_uid: користувач, який створив запис * create_date: дата створення запису * write_uid: останній користувач, який змінив запис * write_date: дата останньої зміни запису * xmlid: ідентифікатор XML для посилання на цей запис (якщо він є) у форматі module.name * noupdate: логічне значення, яке повідомляє, чи буде запис оновлено чи ні

Операції

Набори записів є незмінними, але набори однієї моделі можна комбінувати за допомогою різних операцій із наборами, повертаючи нові набори записів.

  • запис у наборі повертає, чи присутній запис (який має бути 1-елементним набором записів) у наборі. запис не в наборі є зворотною операцією

  • set1 <= set2 і set1 < set2 повертають, чи є set1 підмножиною set2 (відповідно strict)

  • set1 >= set2 і set1 > set2 повертають, чи є set1 надмножиною set2 (відповідно strict)

  • set1 | set2 повертає об’єднання двох наборів записів, новий набір записів, що містить усі записи, присутні в будь-якому джерелі

  • set1 & set2 повертає перетин двох наборів записів, новий набір записів, що містить лише записи, присутні в обох джерелах

  • set1 - set2 повертає новий набір записів, що містить лише записи set1, яких не в set2

Набори записів можна ітерувати, тому для трансформації доступні звичайні інструменти Python (map(), sorted(), ifilter(), …), однак вони повертають або list або iterator, видаляючи можливість викликати методи для їхнього результату або використовувати операції з наборами.

Тому набори записів забезпечують такі операції, повертаючи самі набори записів (якщо це можливо):

Фільтр

Model.filtered(func)[source]

Повертає записи в self задовільний func.

Параметри

func (callable or str) – функція або послідовність назв полів, розділених крапками

Повертає

набір записів, що задовольняє функцію func, може бути порожнім.

# only keep records whose company is the current user's
records.filtered(lambda r: r.company_id == user.company_id)

# only keep records whose partner is a company
records.filtered("partner_id.is_company")
Model.filtered_domain(domain)[source]

Карта

Model.mapped(func)[source]

Застосуйте func до всіх записів у self і поверніть результат як список або набір записів (якщо func повертає набори записів). В останньому випадку порядок поверненого набору записів є довільним.

Параметри

func (callable or str) – функція або послідовність назв полів, розділених крапками

Повертає

self, якщо func є помилковим, результат func застосовується до всіх записів self.

Тип повернення

list or recordset

# returns a list of summing two fields for each record in the set
records.mapped(lambda r: r.field1 + r.field2)

Надана функція може бути рядком для отримання значень поля:

# returns a list of names
records.mapped('name')

# returns a recordset of partners
records.mapped('partner_id')

# returns the union of all partner banks, with duplicates removed
records.mapped('partner_id.bank_ids')

Примітка

Починаючи з версії 13, підтримується мультиреляційний доступ до полів, який працює як відображений виклик:

records.partner_id  # == records.mapped('partner_id')
records.partner_id.bank_ids  # == records.mapped('partner_id.bank_ids')
records.partner_id.mapped('name')  # == records.mapped('partner_id.name')

Сортувати

Model.sorted(key=None, reverse=False)[source]

Повертає набір записів self, упорядкований за key.

Параметри
  • key (callable or str or None) – або функція одного аргументу, яка повертає ключ порівняння для кожного запису, або назви поля, або None, у цьому випадку записи впорядковуються відповідно до порядку моделі за замовчуванням

  • reverse (bool) – якщо True, повертає результат у зворотному порядку

# sort records by name
records.sorted(key=lambda r: r.name)

Спадкування та розширення

Odoo надає три різні механізми для модульного розширення моделей:

  • створення нової моделі з існуючої, додаючи нову інформацію до копії, але залишаючи оригінальний модуль як є

  • розширення моделей, визначених в інших модулях на місці, замінюючи попередню версію

  • делегування деяких полів моделі записам, які вона містить

../../../_images/inheritance_methods.png

Класична спадковість

При спільному використанні атрибутів _inherit і _name Odoo створює нову модель, використовуючи існуючу (надається через _inherit) як основу. Нова модель отримує всі поля, методи та метаінформацію (за замовчуванням та інше) зі своєї бази.

class Inheritance0(models.Model):
    _name = 'inheritance.0'
    _description = 'Inheritance Zero'

    name = fields.Char()

    def call(self):
        return self.check("model 0")

    def check(self, s):
        return "This is {} record {}".format(s, self.name)

class Inheritance1(models.Model):
    _name = 'inheritance.1'
    _inherit = 'inheritance.0'
    _description = 'Inheritance One'

    def call(self):
        return self.check("model 1")

та їх використання:

a = env['inheritance.0'].create({'name': 'A'})
b = env['inheritance.1'].create({'name': 'B'})

a.call()
b.call()

дасть:

«Це запис моделі 0 A» «Це запис моделі 1 B»

друга модель успадкувала від першої моделі метод check і його поле name, але перевизначила метод call, як при використанні стандартного успадкування Python.

Розширення

Якщо використовувати _inherit, але не використовувати _name, нова модель замінить існуючу, по суті розширюючи її на місці. Це корисно для додавання нових полів чи методів до існуючих моделей (створених в інших модулях), або для їх налаштування чи переналаштування (наприклад, для зміни порядку сортування за замовчуванням):

class Extension0(models.Model):
_name = 'extension.0'
_description = 'Extension zero'

name = fields.Char(default="A")

class Extension1(models.Model):
_inherit = 'extension.0'

description = fields.Char(default="Extended")
record = env['extension.0'].create({})
record.read()[0]

дасть:

{'name': "A", 'description': "Extended"}

Примітка

Це також призведе до появи різних автоматичних полів, якщо вони не були вимкнені

Делегування

Третій механізм успадкування забезпечує більшу гнучкість (його можна змінити під час виконання), але меншу потужність: за допомогою _inherits модель делегує пошук будь-якого поля, не знайденого в поточній моделі до «дитячих» моделей. Делегування виконується за допомогою полів Reference, автоматично встановлених у батьківській моделі.

Основна відмінність полягає в значенні. Під час використання делегування модель має один замість є один, перетворюючи зв’язок у композицію замість успадкування:

class Screen(models.Model):
    _name = 'delegation.screen'
    _description = 'Screen'

    size = fields.Float(string='Screen Size in inches')

class Keyboard(models.Model):
    _name = 'delegation.keyboard'
    _description = 'Keyboard'

    layout = fields.Char(string='Layout')

class Laptop(models.Model):
    _name = 'delegation.laptop'
    _description = 'Laptop'

    _inherits = {
        'delegation.screen': 'screen_id',
        'delegation.keyboard': 'keyboard_id',
    }

    name = fields.Char(string='Name')
    maker = fields.Char(string='Maker')

    # a Laptop has a screen
    screen_id = fields.Many2one('delegation.screen', required=True, ondelete="cascade")
    # a Laptop has a keyboard
    keyboard_id = fields.Many2one('delegation.keyboard', required=True, ondelete="cascade")
record = env['delegation.laptop'].create({
    'screen_id': env['delegation.screen'].create({'size': 13.0}).id,
    'keyboard_id': env['delegation.keyboard'].create({'layout': 'QWERTY'}).id,
})
record.size
record.layout

призведе до:

13.0
'QWERTY'

і можна писати безпосередньо в делегованому полі:

record.write({'size': 14.0})

Попередження

при використанні успадкування делегування методи не успадковуються, лише поля

Попередження

  • _inherits більш-менш реалізовано, уникайте його, якщо можете;

  • chained _inherits по суті не реалізовано, ми не можемо нічого гарантувати щодо остаточної поведінки.

Інкрементне визначення полів

Поле визначається як атрибут класу в класі моделі. Якщо модель розширено, можна також розширити визначення поля, перевизначивши поле з тим же ім’ям і тим самим типом у підкласі. У цьому випадку атрибути поля беруться з батьківського класу та замінюються тими, що надані в підкласах.

Наприклад, другий клас нижче лише додає підказку до поля state:

class First(models.Model):
    _name = 'foo'
    state = fields.Selection([...], required=True)

class Second(models.Model):
    _inherit = 'foo'
    state = fields.Selection(help="Blah blah blah")

Управління помилками

Модуль винятків Odoo визначає кілька основних типів винятків.

Ці типи розуміються рівнем RPC. Будь-який інший тип винятку, що з’являється до рівня RPC, розглядатиметься як „Помилка сервера“.

Примітка

Якщо ви плануєте запровадити нові винятки, перегляньте модуль odoo.addons.test_exceptions.

exception odoo.exceptions.AccessDenied(message='Access Denied')[source]

Помилка логіна/паролю.

Примітка

Немає відстеження.

Приклад

Коли ви намагаєтесь увійти з неправильним паролем.

exception odoo.exceptions.AccessError(message)[source]

Помилка прав доступу.

Приклад

Коли ви намагаєтесь прочитати запис, що вам заборонено.

exception odoo.exceptions.CacheMiss(record, field)[source]

У кеші відсутні значення.

Приклад

Коли ви намагаєтеся прочитати значення в очищеному кеші.

exception odoo.exceptions.MissingError(message)[source]

Відсутні записи.

Приклад

Коли ви намагаєтеся записати на видалений запис.

exception odoo.exceptions.RedirectWarning(message, action, button_text, additional_context=None)[source]

Попередження з можливістю перенаправлення користувача замість простого відображення попередження.

Параметри
  • message (str) – повідомлення про винятки та зовнішній модальний вміст

  • action_id (int) – id дії, куди потрібно виконати переспрямування

  • button_text (str) – текст, який потрібно розмістити на кнопці, яка ініціює переспрямування.

  • additional_context (dict) – параметр, переданий у action_id. Можна використовувати для обмеження перегляду, наприклад, до active_ids.

exception odoo.exceptions.UserError(message)[source]

Загальна помилка, керована клієнтом.

Зазвичай, коли користувач намагається зробити щось, що не має сенсу з огляду на поточний стан запису. Семантично можна порівняти з загальними 400 кодами стану HTTP.

exception odoo.exceptions.ValidationError(message)[source]

Порушення обмежень python.

Приклад

Коли ви намагаєтеся створити нового користувача з логіном, який уже існує в базі даних.