Chapter 11: Add The Sprinkles

Our real estate module now makes sense from a business perspective. We created specific views, added several action buttons and constraints. However our user interface is still a bit rough. We would like to add some colors to the list views and make some fields and buttons conditionally disappear. For example, the „Sold“ and „Cancel“ buttons should disappear when the property is sold or canceled since it is no longer allowed to change the state at this point.

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

Reference: the documentation related to this chapter can be found in View records and View architectures.

Вбудовані представлення

Примітка

Ціль: наприкінці цього розділу слід додати певний список властивостей до перегляду типу властивості:

Вбудоване представлення списку

У модулі нерухомості ми додали список пропозицій нерухомості. Ми просто додали поле offer_ids з:

<field name="offer_ids"/>

Поле використовує спеціальне подання для estate.property.offer. У деяких випадках ми хочемо визначити окреме представлення списку, яке використовується лише в контексті подання форми. Наприклад, ми хотіли б відобразити список властивостей, пов’язаних із типом власності. Однак для ясності ми хочемо відобразити лише 3 поля: назва, очікувана ціна та стан.

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

from odoo import fields, models

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

    description = fields.Char()
    line_ids = fields.One2many("test_model_line", "model_id")


class TestModelLine(models.Model):
    _name = "test_model_line"
    _description = "Test Model Line"

    model_id = fields.Many2one("test_model")
    field_1 = fields.Char()
    field_2 = fields.Char()
    field_3 = fields.Char()
<form>
    <field name="description"/>
    <field name="line_ids">
        <tree>
            <field name="field_1"/>
            <field name="field_2"/>
        </tree>
    </field>
</form>

У представленні форми test_model ми визначаємо конкретне представлення списку для test_model_line з полями field_1 і field_2.

Приклад можна знайти тут.

Exercise

Додайте вбудоване представлення списку.

  • Додайте поле One2many property_ids до моделі estate.property.type.

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

Віджети

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

Примітка

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

Віджет панелі стану

Відображаються чотири стани: Новий, Пропозиція отримана, Пропозиція прийнята та Продано.

Щоразу, коли ми додавали поля до наших моделей, нам (майже) ніколи не доводилося турбуватися про те, як ці поля виглядатимуть в інтерфейсі користувача. Наприклад, для поля Date передбачено засіб вибору дати, а поле One2many автоматично відображається у представленні списку. Odoo вибирає правильний „віджет“ залежно від типу поля.

Однак у деяких випадках нам потрібно конкретне представлення поля, яке можна зробити завдяки атрибуту widget. Ми вже використовували його для поля tag_ids, коли використовували атрибут widget="many2many_tags". Якби ми його не використовували, то поле відображалося б у представленні списку.

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

Exercise

Використовуйте віджет рядка стану.

Використовуйте віджет statusbar, щоб відобразити state estate.property, як показано в Цілі цього розділу.

Порада: простий приклад можна знайти тут.

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

Те саме поле кілька разів у представленні

Додайте поле лише один раз до списку або представлення форми. Додавання кілька разів не підтримується.

Порядок списку

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

Примітка

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

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

Модель

Odoo пропонує кілька способів встановлення порядку за замовчуванням. Найпоширенішим способом є визначення атрибута _order безпосередньо в моделі. Таким чином, отримані записи дотримуватимуться детермінованого порядку, який буде узгодженим у всіх поданнях, у тому числі під час програмного пошуку записів. За замовчуванням порядок не вказано, тому записи будуть отримані в недетермінованому порядку залежно від PostgreSQL.

Атрибут _order приймає рядок, що містить список полів, які будуть використовуватися для сортування. Його буде перетворено на речення order_by у SQL. Наприклад:

from odoo import fields, models

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

    description = fields.Char()

Наші записи впорядковані за спаданням id, тобто найвищий іде першим.

Exercise

Додати послідовність моделі.

Визначте такі замовлення у відповідних моделях:

Модель

Порядок

estate.property

ID за спаданням

estate.property.offer

Ціна за спаданням

estate.property.tag

Назва

estate.property.type

Назва

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

Можливе замовлення на рівні моделі. Це має перевагу узгодженого порядку скрізь, де витягується список записів. Однак також можна визначити певний порядок безпосередньо в поданні завдяки атрибуту default_order (приклад).

Вручну

Упорядкування як моделі, так і перегляду забезпечує гнучкість під час сортування записів, але все ще є один випадок, який ми маємо розглянути: упорядкування вручну. Користувач може захотіти сортувати записи залежно від бізнес-логіки. Наприклад, у нашому модулі нерухомості ми хотіли б відсортувати типи власності вручну. Дійсно корисно, щоб типи, які найчастіше використовуються, відображалися у верхній частині списку. Якщо наше агентство нерухомості переважно продає будинки, то зручніше, щоб „Будинок“ стояв перед „Квартира“.

Для цього використовується поле sequence у поєднанні з віджетом handle. Очевидно, що поле sequence має бути першим полем в _order атрибуту.

Exercise

Додати послідовність вручну.

  • Додайте таке поле:

Модель

Поле

Тип

estate.property.type

Послідовність

Integer

  • Додайте послідовність до представлення списку estate.property.type з правильним віджетом.

Порада: ви можете знайти приклад тут: модель і представлення.

Атрибути та параметри

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

Форма

Примітка

Ціль: наприкінці цього розділу вікно форми власності матиме:

  • Умовне відображення кнопок і полів

  • Кольори тегів

Представлення форми з посипаннями

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

Exercise

Додайте параметри віджета.

  • Додайте відповідну опцію до поля property_type_id, щоб запобігти створенню та редагування типу властивості з представлення форми властивості. Перегляньте документацію віджетів Many2one для отримання додаткової інформації.

  • Додайте таке поле:

Модель

Поле

Тип

estate.property.tag

Колір

Integer

Потім додайте відповідну опцію до поля tag_ids, щоб додати вибір кольору до тегів. Перегляньте документацію віджетів FieldMany2ManyTags для отримання додаткової інформації.

In Chapter 5: Finally, Some UI To Play With, we saw that reserved fields were used for specific behaviors. For example, the active field is used to automatically filter out inactive records. We added the state as a reserved field as well. It’s now time to use it! A state field can be used in combination with an invisible attribute in the view to display buttons conditionally.

Exercise

Додайте умовне відображення кнопок.

Use the invisible attribute to display the header buttons conditionally as depicted in this section’s Goal (notice how the „Sold“ and „Cancel“ buttons change when the state is modified).

Tip: do not hesitate to search for invisible= in the Odoo XML files for some examples.

More generally, it is possible to make a field invisible, readonly or required based on the value of other fields. Note that invisible can also be applied to other elements of the view such as button or group.

invisible, readonly and required can have any Python expression as value. The expression gives the condition in which the property applies. For example:

<form>
    <field name="description" invisible="not is_partner"/>
    <field name="is_partner" invisible="True"/>
</form>

This means that the description field is invisible when is_partner is False. It is important to note that a field used in invisible must be present in the view. If it should not be displayed to the user, we can use the invisible attribute to hide it.

Exercise

Use invisible.

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

  • Зробіть кнопки „Прийняти“ та „Відмовитись“ невидимими після встановлення стану пропозиції.

  • Do not allow adding an offer when the property state is „Offer Accepted“, „Sold“ or „Canceled“. To do this use the readonly attribute.

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

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

Список

Примітка

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

Представлення списку з декораторами та додатковим полем Редагований список

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

Exercise

Зробити список доступним для редагування.

Зробити доступними для редагування представлення списку estate.property.offer і estate.property.tag.

З іншого боку, коли модель має багато полів, може виникнути спокуса додати забагато полів у представленні списку та зробити його незрозумілим. Альтернативний спосіб - додати поля, але за бажання зробити їх прихованими. Цього можна досягти завдяки атрибуту optional.

Exercise

Зробіть поле необов’язковим.

Зробіть поле date_availability у списку estate.property необов’язковим і прихованим за замовчуванням.

Нарешті, кольорові коди корисні для візуального підкреслення записів. Наприклад, у модулі нерухомості ми хотіли б відображати відхилені пропозиції червоним кольором, а прийняті – зеленим. Цього можна досягти завдяки атрибуту decoration-{$name} (повний список див. Поля):

<tree decoration-success="is_partner==True">
    <field name="name"/>
    <field name="is_partner" invisible="1"/>
</tree>

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

Exercise

Додайте трохи декораторів.

У представленні списку estate.property:

  • Об’єкти нерухомості з отриманою пропозицією виділені зеленим кольором

  • Власності, пропозицію прийнято, виділено зеленим і жирним шрифтом

  • Об’єкти, що продаються, ігноруються

У представленні списку estate.property.offer:

  • Відмовлені пропозиції червоні

  • Прийняті пропозиції зелені

  • Стани більше не повинно бути видно

Поради:

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

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

Кнопки статистики

Примітка

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

Кнопка статистики

Якщо ви вже використовували деякі функціональні модулі в Odoo, ви, ймовірно, вже стикалися з „кнопкою статистики“. Ці кнопки відображаються у верхньому правому куті представлення форми та забезпечують швидкий доступ до пов’язаних документів. У нашому модулі нерухомості ми хотіли б мати швидке посилання на пропозиції, пов’язані з певним типом нерухомості, як зазначено в Цілі цього розділу.

На цьому етапі підручника ми вже бачили більшість концепцій для цього. Однак єдиного рішення немає, і це все одно може заплутати, якщо ви не знаєте, з чого почати. Ми опишемо покрокове рішення у вправі. Завжди може бути корисно знайти деякі приклади в кодовій базі Odoo, шукаючи oe_stat_button.

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

Ця вправа знайомить із поняттям Пов’язані поля. Найпростіший спосіб зрозуміти це - розглядати його як окремий випадок обчислюваного поля. Наступне визначення поля description:

...

partner_id = fields.Many2one("res.partner", string="Partner")
description = fields.Char(related="partner_id.name")

еквівалентно:

...

partner_id = fields.Many2one("res.partner", string="Partner")
description = fields.Char(compute="_compute_description")

@api.depends("partner_id.name")
def _compute_description(self):
    for record in self:
        record.description = record.partner_id.name

Кожного разу, коли ім’я партнера змінюється, опис змінюється.

Exercise

Додайте кнопку статистики до типу властивості.

  • Додайте поле property_type_id до estate.property.offer. Ми можемо визначити його як пов’язане поле в property_id.property_type_id і встановити його як збережене.

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

  • Додайте поле offer_ids до estate.property.type, яке є інверсією One2many до поля, визначеного на попередньому кроці.

  • Додайте поле offer_count до estate.property.type. Це обчислене поле, яке підраховує кількість пропозицій для певного типу власності (для цього використовуйте offer_ids).

На даний момент у вас є вся необхідна інформація, щоб знати, скільки пропозицій пов’язано з типом нерухомості. Якщо сумніваєтеся, додайте offer_ids і offer_count безпосередньо до представлення. Наступним кроком буде відображення списку після натискання кнопки статистики.

  • Create a stat button on estate.property.type pointing to the estate.property.offer action. This means you should use the type="action" attribute (go back to the end of Chapter 9: Ready For Some Action? if you need a refresher).

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

  • У дії estate.property.offer додайте домен, який визначає property_type_id як рівний active_id (= поточний запис, ось приклад)

Looking good? If not, don’t worry, the next chapter doesn’t require stat buttons ;-)