Chapter 7: Relations Between Models

The previous chapter covered the creation of custom views for a model containing basic fields. However, in any real business scenario we need more than one model. Moreover, links between models are necessary. One can easily imagine one model containing the customers and another one containing the list of users. You might need to refer to a customer or a user on any existing business model.

У нашому модулі нерухомості нам потрібна така інформація про нерухомість:

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

  • the real estate agent who sold the property

  • тип нерухомості: будинок, квартира, пентхаус, замок…

  • перелік тегів, що характеризують нерухомість: затишно, з ремонтом…

  • перелік отриманих пропозицій

Many2one

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

Примітка

Ціль: у кінці цього розділу:

  • слід створити нову модель estate.property.type з відповідним меню, діями та представленнями.

Тип власності
  • три поля Many2one слід додати до моделі estate.property: тип власності, покупець і продавець.

Власність

У нашому модулі нерухомості ми хочемо визначити поняття типу власності. Тип нерухомості – це, наприклад, будинок або квартира. Класифікація властивостей відповідно до їх типу, особливо для вдосконалення фільтрації, є стандартною для бізнесу.

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

Many2one – це просте посилання на інший об’єкт. Наприклад, щоб визначити посилання на res.partner у нашій тестовій моделі, ми можемо написати:

partner_id = fields.Many2one("res.partner", string="Partner")

За домовленістю поля many2one мають суфікс _id. Доступ до даних у партнері можна легко здійснити за допомогою:

print(my_test_object.partner_id.name)

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

foreign keys

На практиці many2one можна побачити як спадний список у представленні форми.

Exercise

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

  • Створіть модель estate.property.type і додайте таке поле:

Поле

Тип

Атрибути

name

Char

обов’язкові

  • Додайте меню, як показано в Цілі цього розділу

  • Додайте поле property_type_id до вашої моделі estate.property та її представлень форми, списку та пошуку

This exercise is a good recap of the previous chapters: you need to create a model, set the model, add an action and a menu, and create a view.

Порада: не забудьте імпортувати нові файли Python у __init__.py, додати нові файли даних у __manifest.py__ або додати права доступу ;-)

Ще раз перезапустіть сервер і оновіть, щоб побачити результати!

У модулі нерухомості все ще бракує двох частин інформації, яку ми хочемо про нерухомість: покупця та продавця. Покупцем може бути будь-яка фізична особа, але з іншого боку продавець повинен бути співробітником агентства нерухомості (тобто користувач Odoo).

В Odoo є дві моделі, які ми зазвичай називаємо:

  • res.partner: партнер - фізична або юридична особа. Це може бути компанія, фізична особа або навіть контактна адреса.

  • res.users: користувачі системи. Користувачі можуть бути „внутрішніми“, тобто мати доступ до серверної частини Odoo. Або вони можуть бути „портальними“, тобто вони не можуть отримати доступ до серверної частини, лише до зовнішньої частини (наприклад, для доступу до своїх попередніх замовлень в електронній комерції).

Exercise

Додайте покупця та продавця.

Додайте покупця та продавця до моделі estate.property за допомогою двох загальних моделей, згаданих вище. Їх слід додати на новій вкладці представлення форми, як показано в Цілі цього розділу.

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

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

Примітка

Об’єкт self.env надає доступ до параметрів запиту та інших корисних речей:

  • self.env.cr або self._cr - об’єкт курсор бази даних; він використовується для запиту до бази даних

  • self.env.uid або self._uid це ідентифікатор бази даних поточного користувача

  • self.env.user - це поточний запис користувача

  • self.env.context або self._context - це контекстний словник

  • self.env.ref(xml_id) повертає запис, що відповідає ідентифікатору XML

  • self.env[model_name] повертає екземпляр даної моделі

Тепер давайте розглянемо інші типи посилань.

Many2many

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

Примітка

Ціль: у кінці цього розділу:

  • слід створити нову модель estate.property.tag із відповідним меню та дією.

Тег власності
  • теги слід додати до моделі estate.property:

Власність

У нашому модулі нерухомості ми хочемо визначити концепцію тегів власності. Тег власності – це, наприклад, нерухомість, яка є „затишною“ або „відремонтованою“.

Властивість може мати many тегів, а тег можна призначити many властивостям. Це підтримується концепцією many2many.

many2many - це двонаправлений множинний зв’язок: будь-який запис на одній стороні може бути пов’язаний із будь-якою кількістю записів на іншій стороні. Наприклад, щоб визначити посилання на модель account.tax у нашій тестовій моделі, ми можемо написати:

tax_ids = fields.Many2many("account.tax", string="Taxes")

За домовленістю поля many2many мають суфікс _ids. Це означає, що до нашої тестової моделі можна додати декілька податків. Він веде себе як список записів, тобто доступ до даних повинен здійснюватися в циклі:

for tax in my_test_object.tax_ids:
    print(tax.name)

Список записів відомий як набір записів, тобто впорядкована колекція записів. Він підтримує стандартні операції Python над колекціями, такі як len() і iter(), а також додаткові операції з наборами, як recs1 | recs2.

Exercise

Додайте таблицю тегів нерухомості.

  • Створіть модель estate.property.tag і додайте таке поле:

Поле

Тип

Атрибути

name

Char

обов’язкові

  • Додайте меню, як показано в Цілі цього розділу

  • Додайте поле tag_ids до вашої моделі estate.property, а також у представленнях її форми та списку

Tip: in the view, use the widget="many2many_tags" attribute as demonstrated here. The widget attribute will be explained in detail in a later chapter of the training. For now, you can try to adding and removing it and see the result ;-)

One2many

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

Примітка

Ціль: у кінці цього розділу:

  • має бути створена нова модель estate.property.offer з відповідною формою та представлення списку.

  • теги слід додати до моделі estate.property:

Пропозиції нерухомості

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

Пропозиція поширюється на one нерухомість, але одна й та сама нерухомість може мати many пропозицій. Знову з’являється концепція many2one. Однак у цьому випадку ми хочемо відобразити список пропозицій для певної власності, тому ми будемо використовувати концепцію one2many.

One2many є зворотним до a many2one. Наприклад, ми визначили в нашій тестовій моделі посилання на модель res.partner завдяки полю partner_id. Ми можемо визначити зворотне співвідношення, тобто список тестових моделей, пов’язаних з нашим партнером:

test_ids = fields.One2many("test_model", "partner_id", string="Tests")

Перший параметр називається comodel, а другий параметр – це поле, яке ми хочемо інверсувати.

За домовленістю поля one2many мають суфікс _ids. Вони ведуть себе як список записів, тобто доступ до даних має здійснюватися в циклі:

for test in partner.test_ids:
    print(test.name)

Небезпека

Оскільки One2many є віртуальним зв’язком, має бути поле Many2one, визначене в комоделі.

Exercise

Додайте таблицю Пропозиція нерухомості.

  • Створіть модель estate.property.offer і додайте наступні поля:

Поле

Тип

Атрибути

Значення

price

Float

status

Selection

немає копії

Прийнято, Відмовлено

partner_id

Many2one (res.partner)

обов’язкові

property_id

Many2one (estate.property)

обов’язкові

  • Створіть представлення списку та вигляд форми з полями price, partner_id і status. Не потрібно створювати дію чи меню.

  • Додайте поле offer_ids до вашої моделі estate.property і в її представленні форми, як показано в Цілі цього розділу.

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

По-друге, незважаючи на те, що поле property_id є обов’язковим, ми не включили його в представлення. Як Odoo дізнається, з якою нерухомістю пов’язана наша пропозиція? Що ж, це частина магії використання фреймворку Odoo: іноді речі визначаються неявно. Коли ми створюємо запис через поле one2many, відповідне поле many2one заповнюється автоматично для зручності.

Still alive? This chapter is definitely not the easiest one. It introduced a couple of new concepts while relying on everything that was introduced before. The next chapter will be lighter, don’t worry ;-)