Chapter 3: Models And Basic Fields

At the end of the previous chapter, we were able to create an Odoo module. However, at this point it is still an empty shell which doesn’t allow us to store any data. In our real estate module, we want to store the information related to the properties (name, description, price, living area…) in a database. The Odoo framework provides tools to facilitate database interactions.

Перш ніж рухатися вперед у вправі, переконайтеся, що модуль estate встановлено, тобто він має відображатися як „Встановлено“ у списку додатків.

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

Не використовуйте змінні глобальні змінні.

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

Об’єктно-реляційне відображення

Довідка: документацію, пов’язану з цією темою, можна знайти в Моделі API.

Примітка

Мета: у кінці цього розділу має бути створена таблиця estate_property:

$ psql -d rd-demo
rd-demo=# SELECT COUNT(*) FROM estate_property;
count
-------
    0
(1 row)

Ключовим компонентом Odoo є рівень ORM. Цей рівень дозволяє уникнути необхідності вручну писати більшість SQL і забезпечує розширюваність і служби безпеки2.

Бізнес-об’єкти оголошуються як класи Python, що розширюють Model, який інтегрує їх в автоматизовану систему збереження.

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

from odoo import models

class TestModel(models.Model):
    _name = "test_model"

Цього визначення достатньо, щоб ORM створив таблицю бази даних під назвою test_model. За домовленістю всі моделі розташовані в каталозі models, і кожна модель визначається у власному файлі Python.

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

  1. Модель визначається у файлі crm/models/crm_recurring_plan.py (див. тут)

  2. Файл crm_recurring_plan.py імпортується в crm/models/__init__.py (див. тут)

  3. Папка models імпортується в crm/__init__.py (див. тут)

Exercise

Визначте модель властивостей нерухомості.

На основі прикладу, наведеного в модулі CRM, створіть відповідні файли та папку для таблиці estate_property.

Після створення файлів додайте мінімальне визначення для моделі estate.property.

Будь-яка зміна файлів Python вимагає перезапуску сервера Odoo. Коли ми перезапустимо сервер, ми додамо параметри -d і -u:

$ ./odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d rd-demo -u estate

-u estate означає, що ми хочемо оновити модуль estate, тобто ORM застосує зміни схеми бази даних. У цьому випадку створюється нова таблиця. -d rd-demo означає, що оновлення має бути виконано в базі даних rd-demo. -u завжди слід використовувати в комбінації з -d.

Під час запуску ви повинні побачити такі попередження:

...
WARNING rd-demo odoo.models: The model estate.property has no _description
...
WARNING rd-demo odoo.modules.loading: The model estate.property has no access rules, consider adding one...
...

Якщо це так, то вам має бути добре! Щоб переконатися, двічі перевірте за допомогою psql, як показано в Ціль.

Exercise

Додати опис.

Додайте _description до вашої моделі, щоб позбутися одного з попереджень.

Поле моделі

Довідка: документацію, пов’язану з цією темою, можна знайти в Моделі API.

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

from odoo import fields, models

class TestModel(models.Model):
    _name = "test_model"
    _description = "Test Model"

    name = fields.Char()

Поле name є Char, яке буде представлено як str Python Unicode і VARCHAR SQL.

Типи

Примітка

Ціль: наприкінці цього розділу до таблиці estate_property слід додати кілька основних полів:

$ psql -d rd-demo

rd-demo=# \d estate_property;
                                            Table "public.estate_property"
    Column       |            Type             | Collation | Nullable |                   Default
--------------------+-----------------------------+-----------+----------+---------------------------------------------
id                 | integer                     |           | not null | nextval('estate_property_id_seq'::regclass)
create_uid         | integer                     |           |          |
create_date        | timestamp without time zone |           |          |
write_uid          | integer                     |           |          |
write_date         | timestamp without time zone |           |          |
name               | character varying           |           |          |
description        | text                        |           |          |
postcode           | character varying           |           |          |
date_availability  | date                        |           |          |
expected_price     | double precision            |           |          |
selling_price      | double precision            |           |          |
bedrooms           | integer                     |           |          |
living_area        | integer                     |           |          |
facades            | integer                     |           |          |
garage             | boolean                     |           |          |
garden             | boolean                     |           |          |
garden_area        | integer                     |           |          |
garden_orientation | character varying           |           |          |
Indexes:
    "estate_property_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "estate_property_create_uid_fkey" FOREIGN KEY (create_uid) REFERENCES res_users(id) ON DELETE SET NULL
    "estate_property_write_uid_fkey" FOREIGN KEY (write_uid) REFERENCES res_users(id) ON DELETE SET NULL

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

Прості приклади полів Boolean, Float, Char, Text, Date і Selection.

Exercise

Додайте основні поля до таблиці Нерухомість.

Додайте в таблицю такі основні поля:

Поле

Тип

name

Char

description

Text

postcode

Char

date_availability

Дата

expected_price

Float

selling_price

Float

bedrooms

Integer

living_area

Integer

facades

Integer

garage

Boolean

garden

Boolean

garden_area

Integer

garden_orientation

Selection

Поле garden_orientation повинно мати 4 можливі значення: „Північ“, „Південь“, „Схід“ і „Захід“. Список вибору визначається як список кортежів, приклад див. тут.

Коли поля додано до моделі, перезапустіть сервер за допомогою -u estate

$ ./odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d rd-demo -u estate

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

Загальні атрибути

Примітка

Ціль: у кінці цього розділу стовпці name і expected_price не повинні мати значення null в таблиці estate_property:

rd-demo=# \d estate_property;
                                            Table "public.estate_property"
    Column       |            Type             | Collation | Nullable |                   Default
--------------------+-----------------------------+-----------+----------+---------------------------------------------
...
name               | character varying           |           | not null |
...
expected_price     | double precision            |           | not null |
...

Подібно до самої моделі, її поля можна налаштувати, передавши атрибути конфігурації як параметри:

name = fields.Char(required=True)

Деякі атрибути доступні для всіх полів, ось найпоширеніші:

string (unicode, за умовчанням: назва поля)

Мітка поля в інтерфейсі користувача (видима користувачами).

required (bool, за умовчанням: False)

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

help (str, за умовчанням: '')

Надає розширену довідкову підказку для користувачів в інтерфейсі користувача.

index (bool, за умовчанням: False)

Запитує, щоб Odoo створив індекс бази даних для стовпця.

Exercise

Встановити атрибути для існуючих полів.

Додайте такі атрибути:

Поле

Атрибут

name

обов’язкові

expected_price

обов’язкові

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

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

Посилання: документацію щодо цієї теми можна знайти в Автоматичні поля.

Можливо, ви помітили, що ваша модель має кілька полів, які ви ніколи не визначали. Odoo створює кілька полів у всіх моделях1. Ці поля керуються системою, і в них не можна записувати, але їх можна прочитати, якщо це буде корисно або необхідно:

id (Id)

Унікальний ідентифікатор для запису моделі.

create_date (Datetime)

Дата створення запису.

create_uid (Many2one)

Користувач, який створив запис.

write_date (Datetime)

Дата останньої зміни запису.

write_uid (Many2one)

Користувач, який останній змінював запис.

Now that we have created our first model, let’s add some security!

1

можна вимкнути автоматичне створення деяких полів

2

написання необроблених запитів SQL можливе, але вимагає обережності, оскільки воно обходить усі механізми автентифікації та безпеки Odoo.