ORM API¶
- Модуль Object Relational Mapping:
Ієрархічна структура
Узгодженість і перевірка обмежень
Метадані об’єкта залежать від його статусу
Оптимізована обробка за складним запитом (кілька дій одночасно)
Значення полів за замовчуванням
Оптимізація дозволів
Постійний об’єкт: DB postgresql
Перетворення даних
Багаторівнева система кешування
Два різних механізми успадкування
- Багатий набір типів полів:
classical (varchar, integer, boolean, …)
relational (one2many, many2one, many2many)
functional
Моделі¶
Поля моделі визначаються як атрибути самої моделі:
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.
- _sql_constraints = []¶
Обмеження SQL [(name, sql_def, message)]
- _register = False¶
Видимість реєстру
- _abstract = True¶
Чи є модель abstract.
Перегляньте також
- _transient = False¶
Чи є модель transient.
Перегляньте також
- _name = None¶
Назва моделі (у крапковій нотації, простір назв модуля)
- _description = None¶
Неформальна назва моделі
- _inherit = ()¶
Моделі, успадковані від Python:
- тип
str або list(str)
- _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оператори.
- _fold_name = 'fold'¶
Поле для визначення згорнутих груп у представленнях канбан
AbstractModel¶
- odoo.models.AbstractModel[source]¶
alias of
odoo.models.BaseModel
Модель¶
- class odoo.models.Model(env, ids, prefetch_ids)[source]¶
Основний супер-клас для звичайних моделей Odoo, що зберігаються в базі даних.
Моделі Odoo створюються шляхом успадкування цього класу:
class user(Model): ...
Пізніше система створить екземпляр класу один раз для бази даних (у якій встановлено модуль класу).
- _auto = True¶
Чи потрібно створити таблицю бази даних. Якщо встановлено значення
False, замінітьinit(), щоб створити таблицю бази даних.Автоматично встановлюється значення
TrueдляModelіTransientModel,FalseдляAbstractModel.Порада
Щоб створити модель без жодної таблиці, успадкуйте від
AbstractModel.
- _abstract = False¶
Чи є модель abstract.
Перегляньте також
TransientModel¶
- class odoo.models.TransientModel(env, ids, prefetch_ids)[source]¶
Модель супер-класу для тимчасових записів, призначених для тимчасової стійкості та регулярної очистки.
TransientModel має спрощене керування правами доступу, усі користувачі можуть створювати нові записи та мати доступ лише до створених ними записів. Суперкористувач має необмежений доступ до всіх записів TransientModel.
- _transient_max_count = 0¶
Максимальна кількість тимчасових записів, необмежена, якщо
0
- _transient_max_hours = 1.0¶
Максимальний час простою (у годинах), необмежений, якщо
0
- _transient_vacuum()[source]¶
Очистити тимчасові записи.
Це від’єднує старі записи від таблиць перехідної моделі щоразу, коли досягаються умови
_transient_max_countабо_transient_max_hours(якщо такі є).Фактичне очищення відбуватиметься лише раз на 5 хвилин. Це означає, що цей метод можна викликати часто (наприклад, щоразу, коли створюється новий запис).
Приклад з активними значеннями max_hours та max_count:
Припустимо, max_hours = 0.2 (тобто 12 хвилин), max_count = 20, у таблиці 55 рядків, 10 створено/змінено за останні 5 хвилин, ще 12 створено/змінено між 5 та 10 хвилинами тому, решта створено/змінено більше 12 хвилин тому.
vacuum на основі віку залишать 22 рядки, створені/змінені за останні 12 хвилин
vacuum на основі підрахунку знищить ще 12 рядків. А не лише 2, інакше кожне додавання призвело б до повторного досягнення максимуму.
10 рядків, створених/змінених за останні 5 хвилин, НЕ будуть видалені
Поля¶
- class odoo.fields.Field[source]¶
Дескриптор поля містить визначення поля та керує доступом та призначенням відповідного поля в записах. Під час створення екземпляра поля можуть бути надані такі атрибути:
- Параметри
string (str) – мітка поля, яке бачать користувачі; якщо не встановлено, ORM приймає назву поля в класі (з великої літери).
help (str) – підказка поля, яку бачать користувачі
readonly (bool) – чи є поле лише для читання (за замовчуванням:
False). Це впливає лише на інтерфейс користувача. Будь-яке призначення полів у коді працюватиме (якщо поле є збереженим або інверсійним полем).required (bool) – чи обов’язкове значення поля (за замовчуванням:
False)index (str) – чи індексовано поле в базі даних, а також тип індексу. Примітка: це не впливає на незбережені та віртуальні поля. Можливі значення: *
"btree"абоTrue: стандартний індекс, підходить для many2one *"btree_not_null": індекс BTREE без значень NULL (корисно, коли більшість значень є NULL або коли NULL ніколи не шукається) *"trigram": узагальнений інвертований індекс (GIN) з триграмами (підходить для повнотекстового пошуку) *NoneабоFalse: немає індексу (за замовчуванням)default (value or callable) – значення поля за умовчанням; це або статичне значення, або функція, яка приймає recordset і повертає значення; використовуйте
default=None, щоб відхилити значення за замовчуванням для поля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) – назва методу, який обчислює поле .. див. також:: Додаткові поля/Обчислювальні поля
precompute (bool) – чи слід обчислювати поле перед вставкою запису в базу даних. Слід використовувати для ручного визначення деяких полів як precompute=True, коли поле можна обчислити перед вставкою запису. (наприклад, уникати полів статистики на основі пошуку/читання_групи), many2one посилання на попередній запис, … (за замовчуванням:
False) .. попередження:: Попереднє обчислення відбувається лише тоді, коли для create() не надано явного значення та значення за замовчуванням. Це означає, що значення за замовчуванням вимикає попереднє обчислення, навіть якщо поле вказано як precompute=True. Попереднє обчислення поля може бути контрпродуктивним, якщо записи заданої моделі не створюються пакетно. Розглянемо ситуацію, коли багато записів створюються один за одним. Якщо поле не обчислюється попередньо, воно зазвичай обчислюється пакетно під час flush(), і механізм попередньої вибірки допоможе зробити обчислення ефективним. З іншого боку, якщо поле обчислюється попередньо, обчислення буде виконуватися одне за одним, і тому не зможе скористатися перевагами механізму попередньої вибірки. Згідно з вищезазначеним зауваженням, попередньо обчислені поля можуть бути цікавими в рядках типу «one2many», які зазвичай створюються пакетно самим ORM, за умови, що вони створюються шляхом запису в запис, який їх містить.compute_sudo (bool) – чи потрібно переобчислювати поле від імені суперкористувача, щоб обійти права доступу (за замовчуванням
Trueдля збережених полів,Falseдля незбережених полів)recursive (bool) – чи має поле рекурсивні залежності (поле
Xмає залежність, подібну доparent_id.X); оголошення рекурсивного поля має бути явним, щоб гарантувати правильність переобчисленняinverse (str) – назва методу, який інвертує поле (необов’язково)
search (str) – назва методу, який реалізує пошук по полю (необов’язково)
related (str) – послідовність назв полів
default_export_compatible (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.Binary[source]¶
Інкапсулює двійковий вміст (наприклад, файл).
- Параметри
attachment (bool) – чи слід зберігати поле як
ir_attachmentабо у стовпчику таблиці моделі (за замовчуванням:True).
- class odoo.fields.Html[source]¶
Інкапсулює вміст html-коду.
- Параметри
sanitize (bool) – чи потрібно очищати значення (за замовчуванням:
True)sanitize_overridable (bool) – чи можуть користувачі групи
base.group_sanitize_overrideобійти очищення (за замовчуванням:False)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.
- 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“ – для всіх записів з цим параметром буде встановлено значення за замовчуванням визначення поля - „set VALUE“ – для всіх записів з цим параметром буде встановлено задане значення - <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.Рядок у відповідному форматі сервера:
FalseабоNone.
Клас полів Date і Datetime має допоміжні методи для спроб перетворення на сумісний тип:
to_date()перетвориться наdatetime.dateto_datetime()перетвориться наdatetime.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 start_of(value, granularity)[source]¶
Об’єкт дати/часу, що відповідає початку вказаного періоду.
- Параметри
value – початкова дата або час.
granularity – тип періоду в рядку, може бути рік, квартал, місяць, тиждень, день або година.
- Повертає
об’єкт дати/часу, що відповідає початку вказаного періоду.
- static end_of(value, granularity)[source]¶
Отримати кінець періоду часу за датою або часом.
- Параметри
value – початкова дата або час.
granularity – Тип періоду в рядку, може бути рік, квартал, місяць, тиждень, день або година.
- Повертає
Об’єкт дати/часу, що відповідає початку вказаного періоду.
- static add(value, *args, **kwargs)[source]¶
Повернути суму
valueіrelativedelta.- Параметри
value – початкова дата або час.
args – позиційні аргументи передавати безпосередньо до
relativedelta.kwargs – ключове слово args для передачі безпосередньо до
relativedelta.
- Повертає
отриману дату/час.
- static subtract(value, *args, **kwargs)[source]¶
Повертає різницю між
valueтаrelativedelta.- Параметри
value – початкова дата або час.
args – позиційні аргументи передавати безпосередньо до
relativedelta.kwargs – ключове слово args для передачі безпосередньо до
relativedelta.
- Повертає
отриману дату/час.
- static today(*args)[source]¶
Поверніть поточний день у форматі, очікуваному ORM.
Примітка
Ця функція може бути використана для обчислення значень за замовчуванням.
- static context_today(record, timestamp=None)[source]¶
Повертає поточну дату у часовому поясі клієнта у форматі, придатному для полів дати.
Примітка
Цей метод можна використовувати для обчислення значень за замовчуванням.
- Параметри
record – набір записів, з якого буде отримано часовий пояс.
timestamp (datetime) – необов’язкове значення часу, яке буде використовуватися замість поточної дати та часу (це має бути час, звичайні дати не можуть конвертуватися між часовими поясами).
- Тип повернення
date
- class odoo.fields.Datetime[source]¶
Інкапсулює об’єкт python
datetime.- static start_of(value, granularity)[source]¶
Об’єкт дати/часу, що відповідає початку вказаного періоду.
- Параметри
value – початкова дата або час.
granularity – тип періоду в рядку, може бути рік, квартал, місяць, тиждень, день або година.
- Повертає
об’єкт дати/часу, що відповідає початку вказаного періоду.
- static end_of(value, granularity)[source]¶
Отримати кінець періоду часу за датою або часом.
- Параметри
value – початкова дата або час.
granularity – Тип періоду в рядку, може бути рік, квартал, місяць, тиждень, день або година.
- Повертає
Об’єкт дати/часу, що відповідає початку вказаного періоду.
- static add(value, *args, **kwargs)[source]¶
Повернути суму
valueіrelativedelta.- Параметри
value – початкова дата або час.
args – позиційні аргументи передавати безпосередньо до
relativedelta.kwargs – ключове слово args для передачі безпосередньо до
relativedelta.
- Повертає
отриману дату/час.
- static subtract(value, *args, **kwargs)[source]¶
Повертає різницю між
valueтаrelativedelta.- Параметри
value – початкова дата або час.
args – позиційні аргументи передавати безпосередньо до
relativedelta.kwargs – ключове слово args для передачі безпосередньо до
relativedelta.
- Повертає
отриману дату/час.
- static now(*args)[source]¶
Повертає поточний день і час у форматі, який очікує ORM.
Примітка
Ця функція може бути використана для обчислення значень за замовчуванням.
- static context_timestamp(record, timestamp)[source]¶
Повертає задану мітку часу, перетворену в часовий пояс клієнта.
Примітка
Цей метод не призначено для використання як ініціалізатор за замовчуванням, оскільки поля часу даних автоматично конвертуються при відображенні на стороні клієнта. Для значень за замовчуванням слід використовувати
now().- Параметри
record – набір записів, з якого буде отримано часовий пояс.
timestamp (datetime) – значення місцевого часу (виражене в UTC) для перетворення в часовий пояс клієнта.
- Повертає
мітку часу перетворено на час з урахуванням часового поясу у контекстному часовому поясі.
- Тип повернення
datetime
Реляційні поля¶
- class odoo.fields.Many2one[source]¶
Значенням такого поля є набір записів розміром 0 (жодного запису) або 1 (один запис).
- Параметри
comodel_name (str) – назва цільової моделі
Обов'язкова, за винятком пов’язаних або розширених полів.domain – необов’язковий домен для встановлення на значеннях-кандидатах на стороні клієнта (домен або вираз Python, який буде оцінено для надання домену)
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_namedomain – необов’язковий домен для встановлення на значеннях-кандидатах на стороні клієнта (домен або вираз Python, який буде оцінено для надання домену)
context (dict) – необов’язковий контекст для використання на стороні клієнта під час роботи з цим полем
auto_join (bool) – чи створюються об’єднання при пошуку за цим полем (за замовчуванням:
False)
Атрибути
comodel_nameтаinverse_nameє обов’язковими, окрім випадків пов’язаних полів або розширень полів.
- class odoo.fields.Many2many[source]¶
Поле many2many; значенням такого поля є набір записів.
- Параметри
comodel_name – назва цільової моделі (рядок) обов’язкова, за винятком випадку пов’язаних або розширених полів
relation (str) – необов’язкова назва таблиці, яка зберігає відношення в базі даних
column1 (str) – необов’язкова назва стовпця, що посилається на «ці» записи в таблиці
relationcolumn2 (str) – необов’язкова назва стовпця, що посилається на «ті» записи в таблиці
relation
Атрибути
relation,column1таcolumn2є необов’язковими. Якщо їх не задано, імена автоматично генеруються з імен моделей, якщоmodel_nameтаcomodel_nameвідрізняються!Зауважте, що наявність декількох полів з неявними параметрами зв’язку на даній моделі з тією самою комоделлю не сприймається ORM, оскільки ці поля будуть використовувати ту саму таблицю. ORM не дозволяє двом полям типу many2many використовувати однакові параметри зв’язку, за винятком випадків, коли
в обох полях використовується однакова модель, комодель, і параметри зв’язку є явними; або
хоча б одне поле належить моделі з
_auto = False.
- Параметри
domain – необов’язковий домен для встановлення на значеннях-кандидатах на стороні клієнта (домен або вираз Python, який буде оцінено для надання домену)
context (dict) – необов’язковий контекст для використання на стороні клієнта під час роботи з цим полем
check_company (bool) – Позначте поле для перевірки у
_check_company(). Додайте домен компанії за замовчуванням залежно від атрибутів поля.
- class odoo.fields.Command[source]¶
Поля
One2manyтаMany2manyочікують спеціальної команди для маніпулювання відношенням, яке вони реалізують.Внутрішньо кожна команда являє собою кортеж із 3 елементів, де перший елемент - обов’язкове ціле число, що ідентифікує команду, другий елемент — це або пов’язаний ідентифікатор запису, до якого потрібно застосувати команду (команди update, delete, unlink та link), або 0 (команди create, clear та set), третій елемент - це або
valuesдля запису в записі (команди create та update), або новий списокidsпов’язаних записів (команди set), або 0 (команди delete, unlink, link та clear).За допомогою Python ми заохочуємо розробників створювати нові команди за допомогою різних функцій цього простору імен. Ми також заохочуємо розробників використовувати константи-ідентифікатори команд під час порівняння першого елемента існуючих команд.
Через RPC неможливо використовувати ні функції, ні назви констант команд. Натомість потрібно записати літеральний кортеж з 3 елементів, де перший елемент = це цілочисельний ідентифікатор команди.
- CREATE = 0¶
- UPDATE = 1¶
- DELETE = 2¶
- UNLINK = 3¶
- LINK = 4¶
- CLEAR = 5¶
- SET = 6¶
- classmethod create(values: dict)[source]¶
Створіть нові записи в комоделі, використовуючи
values, зв’яжіть створені записи зself.У випадку відношення
Many2many, у комоделі створюється один унікальний новий запис таким чином, що всі записи вselfпов’язані з новим записом.У випадку відношення
One2many, один новий запис створюється в комоделі для кожного запису вselfтаким чином, що кожен запис уselfпов’язаний рівно з одним із нових записів.Повертає команду triple
(CREATE, 0, values)
- classmethod update(id: int, values: dict)[source]¶
Напишіть
valuesу пов’язаному записі.Повертає команду triple
(UPDATE, id, values)
- classmethod delete(id: int)[source]¶
Видаляэ пов’язаний запис з бази даних та видалити його зв’язок з
self.У випадку відношення
Many2manyвидалення запису з бази даних може бути запобігнуте, якщо він все ще пов’язаний з іншими записами.Повертає команду triple
(DELETE, id, 0)
- classmethod unlink(id: int)[source]¶
Видаляє зв’язок між
selfта пов’язаним записом.У випадку відношення
One2many, заданий запис видаляється з бази даних, якщо інверсне поле встановлено якondelete='cascade'. В іншому випадку значення інверсного поля встановлюється на False, а запис зберігається.Повертає команду triple
(UNLINK, id, 0)
- classmethod link(id: int)[source]¶
Додає зв’язок між
selfта пов’язаним записом.Повертає команду triple
(LINK, id, 0)
Псевдореляційні поля¶
- class odoo.fields.Reference[source]¶
Псевдореляційне поле (немає FK в базі даних).
Значення поля зберігається у базі даних у вигляді рядка
stringза зразком"res_model,res_id".
- class odoo.fields.Many2oneReference[source]¶
Псевдореляційне поле (немає FK в базі даних).
Значення поля зберігається в базі даних як
integerid.На відміну від полів
Посилання, модель має бути вказана у поліChar, назва якого має бути вказана в атрибутіmodel_fieldдля поточного поляMany2oneReference.
Обчислювані поля¶
Поля можна обчислити (замість читання безпосередньо з бази даних) за допомогою параметра 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 для цих полів. Це означає, що значення інверсних полів (окрім того, яке запускає інверсний метод) може не давати правильне значення, і це, ймовірно, порушить очікувану поведінку інверсного методу.
Автоматичні поля¶
Поля журналу доступу¶
Ці поля встановлюються та оновлюються автоматично, якщо _log_access увімкнено. Його можна вимкнути, щоб уникнути створення або оновлення тих полів у таблицях, для яких вони не є корисними.
За замовчуванням _log_access має те саме значення, що й _auto
Попередження
_log_access має бути включений на TransientModel.
Зарезервовані назви полів¶
Кілька назв полів зарезервовано для попередньо визначеної поведінки, крім автоматизованих полів. Вони повинні бути визначені в моделі, коли потрібна відповідна поведінка:
- Model.name¶
значення за замовчуванням для
_rec_name, яке використовується для відображення записів у контексті, де потрібне репрезентативне «іменування».
- Model.active¶
перемикає загальну видимість запису, якщо
activeвстановлено наFalse, запис невидимий у більшості пошуків і списків.Спеціальні методи:
- Model.action_archive()[source]¶
Встановлює
activeу значенняFalseдля набору записів, викликаючиtoggle_active()для його поточних активних записів.
- Model.action_unarchive()[source]¶
Встановлює
activeу значенняTrueдля набору записів, викликаючиtoggle_active()для його наразі неактивних записів.
- Model.parent_id¶
default_value
_parent_name, що використовується для організації записів у структурі дерева та дозволяє операториchild_ofіparent_ofу доменах.
- Model.parent_path¶
Коли
_parent_storeмає значення True, використовується для збереження значення, що відображає структуру дерева_parent_name, і для оптимізації операторівchild_ofіparent_ofу домени пошуку. Для належної роботи він має бути оголошений за допомогоюindex=True.
- Model.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
Перегляньте також
Методи search_fetch() та fetch() можна використовувати для заповнення кешу записів, зазвичай у випадках, коли механізм попередньої вибірки працює погано.
Декоратори методів¶
Модуль Odoo API визначає середовища Odoo та декоратори методів.
- odoo.api.model(method)[source]¶
Прикрасьте метод у стилі запису, де
selfє набором записів, але його вміст нерелевантний, має значення лише модель. Такий спосіб:@api.model def method(self, args): ...
- 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.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).
- odoo.api.autovacuum(method)[source]¶
Прикрасьте метод так, щоб він викликався щоденним завданням cron прибирання (модель
ir.autovacuum). Зазвичай це використовується для завдань на кшталт збирання сміття, які не заслуговують на окреме завдання cron.
- 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_create_multi(method)[source]¶
Прикрасьте метод, який приймає список словників і створює кілька записів. Метод може бути викликаний або з одним dict, або зі списком dicts:
record = model.create(vals) records = model.create([vals, ...])
- odoo.api.ondelete(*, at_uninstall)[source]¶
Позначити метод, який буде виконано під час
unlink().Мета цього декоратора - дозволити помилки на стороні клієнта під час від’єднання записів, якщо з точки зору бізнесу видалення таких записів не має сенсу. Наприклад, користувач не повинен мати можливості видалити підтверджене замовлення на продаж.
Хоча це можна реалізувати, просто перевизначивши метод
unlinkу моделі, це має недолік у вигляді несумісності з видаленням модуля. Під час видалення модуля перевизначення може призвести до помилок користувача, але нам не повинно бути байдуже, оскільки модуль видаляється, і тому всі записи, пов’язані з модулем, слід видалити в будь-якому разі.Це означає, що якщо перевизначити параметр
unlink, існує велика ймовірність того, що деякі таблиці/записи можуть залишитися як залишки даних від видаленого модуля. Це призводить до неузгодженого стану бази даних. Крім того, існує ризик конфліктів, якщо модуль буде перевстановлено на цю базу даних.Методи, оздоблені за допомогою
@ondelete, повинні викликати помилку після виконання певних умов, і за домовленістю метод повинен мати назву_unlink_if_<condition>або_unlink_except_<not_condition>.@api.ondelete(at_uninstall=False) def _unlink_if_user_inactive(self): if any(user.active for user in self): raise UserError("Can't delete an active user!") # same as above but with _unlink_except_* as method name @api.ondelete(at_uninstall=False) def _unlink_except_active_user(self): if any(user.active for user in self): raise UserError("Can't delete an active user!")
- Параметри
at_uninstall (bool) – Чи слід викликати декорований метод, якщо модуль, який реалізує цей метод, видаляється. Майже завжди має бути
False, щоб видалення модуля не спричиняло ці помилки.
Небезпека
Параметр
at_uninstallслід встановлювати наTrueлише тоді, коли перевірка, яку ви реалізуєте, застосовується також під час видалення модуля.Наприклад, не має значення, чи під час видалення
saleвидаляються підтверджені замовлення на продаж, оскільки всі дані, що стосуютьсяsale, мають бути видалені в будь-якому випадку, у такому випадкуat_uninstallслід встановити наFalse.Однак, має сенс запобігти видаленню мови за замовчуванням, якщо інші мови не встановлено, оскільки видалення мови за замовчуванням порушить багато базових функцій. У цьому випадку для
at_uninstallслід встановити значенняTrue.
Середовище¶
- class odoo.api.Environment(cr, uid, context, su=False, uid_origin=None)[source]¶
Середовище зберігає різні контекстні дані, що використовуються ORM:
cr: поточний курсор бази даних (для запитів до бази даних);uid: поточний id користувача (для перевірки прав доступу);context: поточний контекстний словник (довільні метадані);su: чи в режимі суперкористувача.
Він забезпечує доступ до реєстру, реалізуючи зіставлення імен моделей з іншими моделями. Він також містить кеш для записів та структуру даних для керування перерахунками.
>>> records.env
<Environment object ...>
>>> records.env.uid
3
>>> 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)
Деякі lazy властивості доступні для доступу до даних середовища (контекстуальних):
- Environment.user¶
Поточний користувач, як єдиний набір записів.
- Повертає
поточний користувач - sudoed
- Тип повернення
res.users record
- Environment.company¶
Повернути поточну компанію (як приклад).
Якщо не вказано в контексті (
allowed_company_ids), використовується резервна копія основної компанії поточного користувача.- Викликає
AccessError – недійсний або неавторизований вміст контекстного ключа
allowed_company_ids.- Повертає
поточна компанія (за замовчуванням=`self.user.company_id`), з поточним середовищем
- Тип повернення
res.company record
Попередження
У режимі sudo перевірки на безпеку не застосовуються! У режимі sudo користувач може отримати доступ до будь-якої компанії, навіть якщо вона не входить до дозволених йому компаній.
Це дозволяє ініціювати міжкомпанійні зміни, навіть якщо поточний користувач не має доступу до цільової компанії.
- Environment.companies¶
Повернути набір записів компаній, увімкнених користувачем.
Якщо не вказано в контексті (
allowed_company_ids), використовуються резервні ідентифікатори компаній поточного користувача.- Викликає
AccessError – недійсний або неавторизований вміст контекстного ключа
allowed_company_ids.- Повертає
поточні компанії (за замовчуванням=`self.user.company_ids`), з поточним середовищем
- Тип повернення
res.company recordset
Попередження
У режимі sudo перевірки на безпеку не застосовуються! У режимі sudo користувач може отримати доступ до будь-якої компанії, навіть якщо вона не входить до дозволених йому компаній.
Це дозволяє ініціювати міжкомпанійні зміни, навіть якщо поточний користувач не має доступу до цільової компанії.
Корисні методи для роботи з навколишнім середовищем¶
- Environment.ref(xml_id, raise_if_not_found=True)[source]¶
Повернути запис, що відповідає заданому
xml_id.- Параметри
- Повертає
Знайдено запис або None
- Викликає
ValueError – якщо запис не знайдено, а
raise_if_not_foundмає значення True
Зміна середовища¶
- Model.with_context([context][, **overrides]) Model[source]¶
Повертає нову версію цього набору записів, приєднану до розширеного контексту.
Розширений контекст - це або наданий
context, у якому об’єднуютьсяoverrides, або поточний контекст, у якому об’єднуютьсяoverrides, наприклад:# 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]¶
Повертає нову версію цього набору записів, приєднану до заданого користувача, у режимі, відмінному від суперкористувача, якщо тільки
userне є суперкористувачем (за домовленістю, суперкористувач завжди знаходиться в режимі суперкористувача).
- Model.with_company(company)[source]¶
Повернути нову версію цього набору записів зі зміненим контекстом, таким чином, щоб:
result.env.company = company result.env.companies = self.env.companies | company
- Параметри
company (
res_companyor int) – головна компанія нового середовища.
Попередження
Під час використання неавторизованої компанії для поточного користувача, доступ до компанії(й) у середовищі може викликати помилку AccessError, якщо це не зроблено в середовищі sudoed.
- Model.with_env(env)[source]¶
Повернути нову версію цього набору записів, приєднану до наданого середовища.
- Параметри
env (
Environment) –
Примітка
Повернений набір записів має той самий об’єкт попередньої вибірки, що й
self.
- Model.sudo([flag=True])[source]¶
Повертає нову версію цього набору записів з увімкненим або вимкненим режимом суперкористувача, залежно від
flag. Режим суперкористувача не змінює поточного користувача та просто обходить перевірку прав доступу.Попередження
Використання команди
sudoможе призвести до перетину меж правил доступу до даних, що може призвести до змішування записів, які мають бути ізольованими (наприклад, записів з різних компаній у багатокомпанійному середовищі).Це може призвести до неінтуїтивних результатів у методах, які вибирають один запис серед багатьох, наприклад, отримання компанії за замовчуванням або вибір специфікації матеріалів.
Примітка
Повернений набір записів має той самий об’єкт попередньої вибірки, що й
self.
Виконання SQL¶
Атрибут cr в середовищах є курсором для поточної транзакції бази даних і дозволяє безпосередньо виконувати SQL або для запитів, які важко виразити за допомогою ORM (наприклад, складні об’єднання), або для продуктивності причини:
self.env.cr.execute("some_sql", params)
Попередження
Виконання необробленого SQL обходить ORM і, як наслідок, правила безпеки Odoo. Будь ласка, переконайтеся, що ваші запити очищені під час використання введених користувачем даних, і надайте перевагу використанню утиліт ORM, якщо вам насправді не потрібно використовувати SQL-запити.
Рекомендований спосіб створення SQL-запитів – використання об’єкта-обгортки
- class odoo.tools.SQL(code: str | odoo.tools.sql.SQL = '', /, *args, **kwargs)[source]¶
Об’єкт, який обгортає SQL-код своїми параметрами, наприклад:
sql = SQL("UPDATE TABLE foo SET a = %s, b = %s", 'hello', 42) cr.execute(sql)
Код надається у вигляді рядка у форматі
%та підтримує як позиційні аргументи (з%s), так і іменовані аргументи (з%(name)s). Однак екрановані символи (наприклад,"%%") не підтримуються. Аргументи призначені для об’єднання з кодом за допомогою оператора форматування%.Обгортка SQL розроблена компонувальною: аргументи можуть бути як фактичними параметрами, так і самими об’єктами SQL:
sql = SQL( "UPDATE TABLE %s SET %s", SQL.identifier(tablename), SQL("%s = %s", SQL.identifier(columnname), value), )
Об’єднаний SQL-код задається списком
sql.code, а відповідні об’єднані параметри задаються спискомsql.params. Це дозволяє об’єднувати будь-яку кількість SQL-термінів без необхідності окремо об’єднувати їхні параметри, що може бути нудним, схильним до помилок і є головним недолікомpsycopg2.sql <https://www.psycopg.org/docs/sql.html>.Друга мета обгортки - запобігти SQL-ін’єкціям. Дійсно, якщо
codeє рядковим літералом (не динамічним рядком), то SQL-об’єкт, створений за допомогоюcode, гарантовано безпечний, за умови, що SQL-об’єкти в його параметрах самі є безпечними.- join(args: Iterable) odoo.tools.sql.SQL[source]¶
Об’єднуйте об’єкти або параметри SQL, використовуючи роздільник
self.
- classmethod identifier(name: str, subname: Optional[str] = None) odoo.tools.sql.SQL[source]¶
Повернути SQL-об’єкт, який представляє ідентифікатор.
Важливо знати про моделі те, що вони не обов’язково виконують оновлення бази даних одразу. Дійсно, з міркувань продуктивності фреймворк затримує переобчислення полів після зміни записів. І деякі оновлення бази даних також затримуються. Тому перед запитом до бази даних потрібно переконатися, що вона містить відповідні дані для запиту. Ця операція називається очищенням і виконує очікувані оновлення бази даних.
Example
# make sure that 'partner_id' is up-to-date in database
self.env['model'].flush_model(['partner_id'])
self.env.cr.execute(SQL("SELECT id FROM model WHERE partner_id IN %s", ids))
ids = [row[0] for row in self.env.cr.fetchall()]
Перед кожним SQL-запитом необхідно скинути дані, необхідні для цього запиту. Існує три рівні скидання, кожен з яких має свій власний API. Можна скинути або все, або всі записи моделі, або деякі конкретні записи. Оскільки затримка оновлень загалом покращує продуктивність, ми рекомендуємо бути конкретними під час скидання.
- Model.flush_model(fnames=None)[source]¶
Обробляє очікувані обчислення та оновлення бази даних на моделі
self. Коли параметр задано, метод гарантує, що принаймні задані поля будуть скинуті до бази даних. Однак можна скинути й інші поля.- Параметри
fnames – необов’язковий ітерабельний список назв полів для очищення
- Model.flush_recordset(fnames=None)[source]¶
Обробляє очікувані обчислення та оновлення бази даних для записів
self. Коли параметр задано, метод гарантує, що принаймні задані поля записівselfбудуть скинуті до бази даних. Однак можна скинути більше полів та записів.- Параметри
fnames – необов’язковий ітерабельний список назв полів для очищення
Оскільки моделі використовують той самий курсор, а Environment містить різні кеші, ці кеші мають бути визнані недійсними під час зміни бази даних у необробленому SQL, інакше подальше використання моделей може стати неузгодженим. Необхідно очищати кеші під час використання CREATE, UPDATE або DELETE у SQL, але не SELECT (який просто читає базу даних).
Example
# make sure 'state' is up-to-date in database
self.env['model'].flush_model(['state'])
self.env.cr.execute("UPDATE model SET state=%s WHERE state=%s", ['new', 'old'])
# invalidate 'state' from the cache
self.env['model'].invalidate_model(['state'])
Так само, як і під час очищення, можна зробити недійсним весь кеш, кеш усіх записів моделі або кеш певних записів. Можна навіть зробити недійсними певні поля в деяких записах або всіх записах моделі. Оскільки кеш загалом покращує продуктивність, ми рекомендуємо бути конкретними під час недійсності.
- Environment.invalidate_all(flush=True)[source]¶
Виключити всі записи з кешу.
- Параметри
flush – чи слід скидати оновлення, що очікують на оновлення, перед їх визнанням недійсними. За замовчуванням значення
True, що забезпечує узгодженість кешу. Не використовуйте цей параметр, якщо ви не знаєте, що робите.
- Model.invalidate_model(fnames=None, flush=True)[source]¶
Зробити кеш усіх записів моделі
selfнедійсним, коли кешовані значення більше не відповідають значенням бази даних. Якщо параметр задано, з кешу будуть недійсними лише задані поля.- Параметри
fnames – необов’язковий ітерований варіант назв полів для анулювання
flush – чи слід скидати оновлення, що очікують на оновлення, перед їх визнанням недійсними. За замовчуванням значення
True, що забезпечує узгодженість кешу. Не використовуйте цей параметр, якщо ви не знаєте, що робите.
- Model.invalidate_recordset(fnames=None, flush=True)[source]¶
Зробити кеш записів у
selfнедійсним, коли кешовані значення більше не відповідають значенням бази даних. Якщо параметр задано, з кешу будуть недійсними лише вказані поля вself.- Параметри
fnames – необов’язковий ітерований варіант назв полів для анулювання
flush – чи слід скидати оновлення, що очікують на оновлення, перед їх визнанням недійсними. За замовчуванням значення
True, що забезпечує узгодженість кешу. Не використовуйте цей параметр, якщо ви не знаєте, що робите.
Вищезазначені методи підтримують узгодженість кешів та бази даних. Однак, якщо залежності обчислених полів були змінені в базі даних, необхідно повідомити моделі про необхідність повторного обчислення обчислених полів. Єдине, що потрібно знати фреймворку, це які поля змінилися в яких записах.
Example
# make sure 'state' is up-to-date in database
self.env['model'].flush_model(['state'])
# use the RETURNING clause to retrieve which rows have changed
self.env.cr.execute("UPDATE model SET state=%s WHERE state=%s RETURNING id", ['new', 'old'])
ids = [row[0] for row in self.env.cr.fetchall()]
# invalidate the cache, and notify the update to the framework
records = self.env['model'].browse(ids)
records.invalidate_recordset(['state'])
records.modified(['state'])
Потрібно з’ясувати, які записи були змінені. Існує багато способів зробити це, можливо, за допомогою додаткових SQL-запитів. У наведеному вище прикладі ми використовуємо переваги пункту ПОВЕРНЕННЯ PostgreSQL для отримання інформації без додаткового запиту. Після узгодження кешу шляхом недійсності, викликаємо метод modified для змінених записів з оновленими полями.
- Model.modified(fnames, create=False, before=False)[source]¶
Повідомляти, що поля будуть або вже були змінені на
self. Це робить кеш недійсним, де це необхідно, та готує переобчислення залежних збережених полів.- Параметри
fnames – ітерований список назв полів, змінених на записах
selfcreate – чи викликається в контексті створення запису
before – чи викликається перед зміною записів
self
Поширені методи ORM¶
Створити/оновити¶
- Model.create(vals_list) records[source]¶
Створює нові записи для моделі.
Нові записи ініціалізуються значеннями зі списку словників
vals_list, а за необхідності - зdefault_get().- Параметри
vals_list (Union[list[dict], dict]) – значення для полів моделі у вигляді списку словників:: [{„field_name“: field_value, …}, …] Для зворотної сумісності,
vals_listможе бути словником. Він обробляється як одиночний список[vals], і повертається один запис. див.write()для отримання детальної інформації- Повертає
Створення записів
- Викликає
AccessError – якщо поточному користувачеві не дозволено створювати записи зазначеної моделі
ValidationError – якщо користувач намагається ввести недійсне значення для поля вибору
ValueError – якщо назва поля, вказане у створених значеннях, не існує.
UserError – якщо в результаті операції в ієрархії об’єктів буде створено цикл (наприклад, встановлення об’єкта як власного батьківського елемента)
- Model.copy(default=None)[source]¶
Дублікат запису
selfоновлює його значеннями за замовчуванням- Параметри
default (dict) – словник значень полів, які потрібно перезаписати в оригінальних значеннях скопійованого запису, наприклад:
{'field_name': overridden_value, ...}- Повертає
Читайте записи
- Model.default_get(fields_list) default_values[source]¶
Повертає значення за замовчуванням для полів у
fields_list. Значення за замовчуванням визначаються контекстом, налаштуваннями користувача за замовчуванням та самою моделлю.- Параметри
fields_list (list) – деякі поля мають значення за замовчуванням
- Повертає
словник, що зіставляє назви полів із відповідними значеннями за замовчуванням, якщо вони мають значення за замовчуванням.
- Тип повернення
Примітка
Незапитані значення за замовчуванням не розглядатимуться, немає потреби повертати значення для полів, назва яких відсутні у
fields_list.
- Model.name_create(name) record[source]¶
Створіть новий запис, викликавши
create(), надаючи лише одне значення: відображувану назву нового запису.Новий запис буде ініціалізовано будь-якими значеннями за замовчуванням, що застосовуються до цієї моделі, або наданими через контекст. Застосовується звичайна поведінка
create().- Параметри
name – назва поля для візуалізації
- Тип повернення
- Повертає
значення пари (id, display_name) створеного запису
- Model.write(vals)[source]¶
Оновлює всі записи в
selfнаданими значеннями.- Параметри
vals (dict) – поля для оновлення та значення, яке потрібно для них встановити
- Викликає
AccessError – якщо користувачеві не дозволено змінювати вказані записи/поля
ValidationError – якщо для полів вибору вказано недійсні значення
UserError – якщо в результаті операції в ієрархії об’єктів буде створено цикл (наприклад, встановлення об’єкта як власного батьківського елемента)
Для числових полів (
Integer,Float) значення має бути відповідного типуДля
Selectionзначення має відповідати значенням вибору (зазвичайstr, інодіint)Для
Many2oneзначення має бути ідентифікатором бази даних запису, який потрібно встановитиОчікуване значення реляційного поля
One2manyабоMany2many– це списокCommand, які маніпулюють відношенням, яке реалізує реалізація. Всього існує 7 команд:create(),update(),delete(),unlink(),link(),clear()таset().Для
Dateта~odoo.fields.Datetimeзначення має бути або датою (часом), або рядком.Попередження
Якщо для полів Date(time) надається рядок, він має бути лише UTC та відформатований відповідно до
odoo.tools.misc.DEFAULT_SERVER_DATE_FORMATтаodoo.tools.misc.DEFAULT_SERVER_DATETIME_FORMATІнші нереляційні поля використовують рядок для значення
Пошук/Читання¶
- Model.browse([ids]) records[source]¶
Повертає набір записів для ідентифікаторів, наданих як параметр у поточному середовищі.
self.browse([7, 18, 12]) res.partner(7, 18, 12)
- Model.search(domain[, offset=0][, limit=None][, order=None])[source]¶
Шукати записи, що відповідають заданому
domainпошук домену.- Параметри
domain – Домен пошуку. Використовуйте порожній список, щоб зіставити всі записи.
offset (int) – кількість результатів для ігнорування (за замовчуванням: немає)
limit (int) – максимальна кількість записів для повернення (за замовчуванням: усі)
order (str) – рядок сортування
- Повертає
щонайбільше
limitзаписів, що відповідають критеріям пошуку- Викликає
AccessError – якщо користувачеві заборонено доступ до запитуваної інформації
Це високорівневий метод, який не слід перевизначати. Його фактична реалізація здійснюється методом
_search().
- Model.search_count(domain[, limit=None]) int[source]¶
Повертає кількість записів у поточній моделі, які відповідають наданому домену.
- Параметри
domain – Домен пошуку. Використовуйте порожній список, щоб зіставити всі записи.
limit – максимальна кількість записів для підрахунку (верхня межа) (за замовчуванням: усі)
Це високорівневий метод, який не слід перевизначати. Його фактична реалізація здійснюється методом
_search().
- Model.search_fetch(domain, field_names[, offset=0][, limit=None][, order=None])[source]¶
Шукає записи, що відповідають заданому
domainпошук домену, та отримує задані поля до кешу. Цей метод подібний до комбінації методівsearch()таfetch(), але виконує обидва завдання з мінімальною кількістю SQL-запитів.- Параметри
domain – Домен пошуку. Використовуйте порожній список, щоб зіставити всі записи.
field_names – колекція назв полів для отримання
offset (int) – кількість результатів для ігнорування (за замовчуванням: немає)
limit (int) – максимальна кількість записів для повернення (за замовчуванням: усі)
order (str) – рядок сортування
- Повертає
щонайбільше
limitзаписів, що відповідають критеріям пошуку- Викликає
AccessError – якщо користувачеві заборонено доступ до запитуваної інформації
- Model.name_search(name='', args=None, operator='ilike', limit=100) records[source]¶
Шукайте записи, які мають відображувану назву, що відповідає даному шаблону
nameу порівнянні з данимoperator, а також відповідає додатковому домену пошуку (args).Це використовується, наприклад, для надання пропозицій на основі часткового значення реляційного поля. Зазвичай має поводитися як протилежне до
display_name, але це не гарантовано.Цей метод еквівалентний виклику
search()з доменом пошуку на основіdisplay_nameта зіставленням id та display_name з результуючим пошуком.- Параметри
- Тип повернення
- Повертає
список пар
(id, display_name)для всіх відповідних записів.
- Model.fetch(field_names)[source]¶
Переконайтеся, що задані поля є в пам’яті для записів у
self, шляхом отримання необхідного з бази даних. Незбережені поля здебільшого ігноруються, за винятком їхніх збережених залежностей. Цей метод слід викликати для оптимізації коду.- Параметри
field_names – колекція назв полів для отримання
- Викликає
AccessError – якщо користувачеві заборонено доступ до запитуваної інформації
Цей метод реалізовано завдяки методам
_search()та_fetch_query(), і його не слід перевизначати.
- Model.read([fields])[source]¶
Зчитати запитувані поля для записів у
selfта повернути їхні значення у вигляді списку словників.- Параметри
- Повертає
список словників, що відображають назви полів на їхні значення, з одним словником на запис
- Тип повернення
- Викликає
AccessError – якщо користувачеві заборонено доступ до запитуваної інформації
ValueError – якщо запитуване поле не існує
Це високорівневий метод, який не передбачається перевизначати. Щоб змінити спосіб зчитування полів з бази даних, див. методи
_fetch_query()та_read_format().
- Model._read_group(domain, groupby=(), aggregates=(), having=(), offset=0, limit=None, order=None)[source]¶
Отримати агрегації полів, визначені за допомогою
aggregates, згруповані за заданими полямиgroupby, де записи фільтруються заdomain.- Параметри
domain (list) – Домен пошуку. Використовуйте порожній список, щоб зіставити всі записи.
groupby (list) – Список групових описів, за якими записи будуть згруповані. Груповий опис – це або поле (тоді записи будуть згруповані за цим полем), або рядок
'field:granularity'. Наразі єдиними підтримуваними рівнями гранулярності є'day','week','month','quarter'або'year', і вони мають сенс лише для полів дати/дати та часу.aggregates (list) – Список специфікацій агрегатів. Кожен елемент - це
'field:agg'(агрегаційне поле з функцією агрегації'agg'). Можливі функції агрегації - це ті, що надаються PostgreSQL,'count_distinct'з очікуваним значенням та'recordset', що діє як'array_agg', перетворений на набір записів.having (list) – Домен, де дійсні «поля» є агрегатами.
offset (int) – необов’язкова кількість груп для пропускання
limit (int) – необов’язкова максимальна кількість груп для повернення
order (str) – необов’язкова специфікація
order by, для перевизначення природного порядку сортування груп див. такожsearch().
- Повертає
список кортежів, що містять у порядку групових та агрегованих значень (зведення):
[(groupby_1_value, ... , aggregate_1_value_aggregate, ...), ...]. Якщо група є пов’язаним полем, його значенням буде набір записів (з правильним набором попередніх вибірок).- Тип повернення
- Викликає
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 та „count_distinct“ з очікуваним значенням.
groupby (list) – Список описів групування, за якими записи будуть згруповані. Опис групування – це або поле (тоді записи будуть згруповані за цим полем), або рядок „field:granularity“. Наразі єдиними підтримуваними рівнями гранулярності є „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* __range: (лише дата/дату й час) словник з field_name:granularity як ключами, що відповідають словнику з ключами: «from» (включно) та «to» (виключно), що відповідають рядковому представленню часових меж групи- Тип повернення
[{„field_name_1“: value, …}, …]
- Викликає
AccessError – якщо користувачеві заборонено доступ до запитуваної інформації
Поля¶
Пошук доменів¶
Домен - це список критеріїв, кожен критерій - це трійка (або список, або кортеж) (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без урахування регістру
likenot ilikeбез урахування регістру
not like=ilikeбез урахування регістру
=likeinдорівнює будь-якому з елементів із
value,valueмає бути списком елементівnot inне дорівнює всім елементам із
valuechild_ofє дочірнім (нащадком) запису
value(значення може бути або одним елементом, або списком елементів).Враховує семантику моделі (тобто після поля зв’язку, названого
_parent_name).parent_ofє батьківським (висхідним) запису
value(значення може бути як одним елементом, так і списком елементів).Враховує семантику моделі (тобто після поля зв’язку, названого
_parent_name).anyзбігається, якщо будь-який запис у зв’язку, що проходить через
field_name(Many2one,One2manyабоMany2many), задовольняє задане значення доменуvalue.not anyзбігається, якщо жоден запис у зв’язку, що обходить
field_name(Many2one,One2manyабоMany2many), не відповідає заданомуvalueдомену.
valueтип змінної, має бути порівнянним (через
operator) з іменованим полем.
Критерії домену можна комбінувати за допомогою логічних операторів у формі prefix:
'&'логічне AND, операція за замовчуванням для комбінування наступних критеріїв. Arity 2 (використовує наступні 2 критерії або комбінації).
'|'логічне OR, арність 2.
'!'логічне NOT, арність 1.
Примітка
Здебільшого для заперечення комбінацій критеріїв. Окремий критерій, як правило, має негативну форму (наприклад,
=->!=,<->>=), що простіше, ніж заперечення позитивного .
Example
Щоб знайти партнерів на ім’я ABC, номер телефону або мобільного телефону яких містить 7620:
[('name', '=', 'ABC'),
'|', ('phone','ilike','7620'), ('mobile', 'ilike', '7620')]
Щоб знайти замовлення на продаж для виставлення рахунків, які містять принаймні один рядок із товаром, якого немає на складі:
[('invoice_status', '=', 'to invoice'),
('order_line', 'any', [('product_id.qty_available', '<=', 0)])]
Від’єднати¶
- Model.unlink()[source]¶
Видаляє записи в
self.- Викликає
AccessError – якщо користувачеві не дозволено видаляти всі задані записи
UserError – якщо запис є властивістю за замовчуванням для інших записів
Запис (набір) інформації¶
- Model.ids¶
Повертає список фактичних ідентифікаторів записів, які відповідають
self.
- odoo.models.env¶
Повертає середовище заданого набору записів.
- тип
- Model.exists() records[source]¶
Повертає підмножину записів у
self, які існують. Може використовуватися як перевірка записів:if record.exists(): ...
Згідно з умовами, нові записи повертаються як існуючі.
- Model.ensure_one()[source]¶
Перевірте, чи поточний набір записів містить один запис.
- Викликає
odoo.exceptions.ValueError –
len(self) != 1
- Model.get_metadata()[source]¶
Повернути деякі метадані про дані записи.
- Повертає
список словників власності для кожного запитуваного запису
- Тип повернення
список словників з такими ключами: * id: object* create_uid: користувач, який створив запис * create_date: дата створення запису * write_uid: останній користувач, який змінив запис * write_date: дата останньої зміни запису * xmlid: XML ID, який використовуватиметься для посилання на цей запис (якщо такий є), у форматі
module.name* xmlids: список словників з xmlid у форматіmodule.nameта noupdate як логічне значення * 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]¶
Повернути записи в
self, що задовольняють домен і зберігають той самий порядок.- Параметри
domain – Домен пошуку.
Карта¶
- 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.grouped(key)[source]¶
Охоче групує записи
selfзаkey, повертаючи словник з результатуkeyдо наборів записів. Усі результуючі набори записів гарантовано є частиною одного набору попередньої вибірки.Надає зручний метод для розділення існуючих наборів записів без накладних витрат
read_group(), але не виконує агрегацію.Примітка
на відміну від
itertools.groupby(), не звертає уваги на порядок вводу, проте компроміс полягає в тому, що він не може бути lazy
Спадкування та розширення¶
Odoo надає три різні механізми для модульного розширення моделей:
створення нової моделі з існуючої, додаючи нову інформацію до копії, але залишаючи оригінальний модуль як є
розширення моделей, визначених в інших модулях на місці, замінюючи попередню версію
делегування деяких полів моделі записам, які вона містить
Класична спадковість¶
При спільному використанні атрибутів _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.UserError(message)[source]¶
Загальна помилка, керована клієнтом.
Зазвичай, коли користувач намагається зробити щось, що не має сенсу з огляду на поточний стан запису. Семантично можна порівняти з загальними 400 кодами стану HTTP.
- 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.AccessDenied(message='Access Denied')[source]¶
Помилка логіна/паролю.
Примітка
Немає відстеження.
Приклад
Коли ви намагаєтесь увійти з неправильним паролем.
- exception odoo.exceptions.AccessError(message)[source]¶
Помилка прав доступу.
Приклад
Коли ви намагаєтесь прочитати запис, що вам заборонено.
- exception odoo.exceptions.CacheMiss(record, field)[source]¶
У кеші відсутні значення.
Приклад
Коли ви намагаєтеся прочитати значення в очищеному кеші.