第12章:添加彩色糖屑?

我們的房地產模塊現在從商業角度看起來很有意義。我們創建了 特定視圖 ,添加了幾個 操作按鈕約束條件 。然而,我們的用戶界面還有些粗糙。我們想在列表視圖中添加一些顏色,并使一些字段和按鈕在條件下消失。例如,當物業已售出或取消時,’已售出’和’取消’按鈕應該消失,因為此時不再允許更改狀態。

本章節僅涵蓋了視圖中的一小部分功能。請閱讀參考文檔以獲取更全面的概述。

參考 : 本章相關文檔可在 視圖 中找到。

內聯視圖?

注解

目標 : 完成本節后,應向屬性類型視圖添加特定的屬性列表:

內聯列表視圖

在房地產模塊中,我們為一個屬性添加了一個報價列表。我們只需添加字段 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_1field_2 。

可以在 這里 找到一個例子。

Exercise

添加一個內聯列表視圖。

  • One2many 字段 property_ids 添加到 estate.property.type 模型中。

  • estate.property.type 表單視圖中添加字段,如本節的 **目標 ** 所示。

小部件?

參考 : 本節相關文檔可以在 字段小部件 中找到。

注解

目標 :本節結束時,應使用特定的小部件顯示屬性的狀態:

狀態欄小部件

展示了四種狀態:新建、已收到報價、已接受報價和已售出。

每當我們向我們的模型添加字段時,我們(幾乎)從來不必擔心這些字段在用戶界面中會是什么樣子。例如,對于“日期”字段,提供了一個日期選擇器,而“One2many”字段會自動顯示為列表。Odoo根據字段類型選擇正確的“小部件”。

然而,在某些情況下,我們希望字段有特定的表示方式,這可以通過 widget 屬性實現。我們已經在使用 widget="many2many_tags" 屬性時使用了它來處理 tag_ids 字段。如果我們沒有使用它,那么該字段將顯示為列表。

每種字段類型都有一組小部件,可以用來微調其顯示。有些小部件還可以使用額外的選項。詳細列表可以在 字段小部件 中找到。

Exercise

使用狀態欄小部件。

使用“狀態欄”小部件來顯示本節目標中所示的“estate.property”的“狀態”。

提示:可以在 這里 找到一個簡單的例子。

警告

在視圖中多次使用同一字段

在列表或表單視圖中只能添加一個字段。不支持添加多個相同的字段。

訂單列表?

參考 : 本節相關文檔可以在 模型 中找到。

注解

目標 :本節結束時,所有列表應默認以確定性順序顯示。屬性類型可以手動排序。

在之前的練習中,我們創建了幾個列表視圖。然而,我們從未指定默認情況下記錄的排序方式。這對于許多業務場景非常重要。例如,在我們的房地產模塊中,我們希望將最高的報價顯示在列表的頂部。

模型?

Odoo 提供了幾種設置默認順序的方法。最常見的方法是直接在模型中定義 _order 屬性。這樣,檢索到的記錄將遵循確定性順序,在所有視圖中都是一致的,包括在編程搜索記錄時。默認情況下,沒有指定順序,因此記錄將以非確定性順序檢索,這取決于 PostgreSQL。

_order 屬性接受一個包含字段列表的字符串,這些字段將用于排序。它將被轉換為 SQL 中的 order_by 子句。例如:

from odoo import fields, models

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

    description = fields.Char()

我們的記錄按照降序排列,意味著最高的記錄排在第一位。

Exercise

添加模型排序。

在相應的模型中定義以下訂單:

模型

排序

estate.property

按 ID 降序排列

estate.property.offer

價格降序

estate.property.tag

名稱

estate.property.type

名稱

視圖?

可以在模型層面進行排序。這樣做的好處是在檢索記錄列表時,無論在哪里都可以保持一致的順序。但是,也可以通過視圖直接定義特定的順序,這要歸功于“default_order”屬性( `示例<https://github.com/odoo/odoo/blob/892dd6860733c46caf379fd36f57219082331b66/addons/crm/report/crm_activity_report_views.xml#L30>`__)。

手動?

模型和視圖排序都允許在排序記錄時靈活處理,但仍有一種情況需要考慮:手動排序。用戶可能希望根據業務邏輯對記錄進行排序。例如,在我們的房地產模塊中,我們希望手動對房地產類型進行排序。確實有用的是將最常用的類型顯示在列表的頂部。如果我們的房地產代理主要銷售房屋,則將“House”放在“Apartment”之前更為方便。

為此,需要使用“sequence”字段與“handle”小部件相結合。顯然,“sequence”字段必須是“_order”屬性中的第一個字段。

Exercise

添加手動排序。

  • 添加以下字段:

模型

字段

類型

estate.property.type

序列

整數

  • 使用正確的小部件將序列添加到 estate.property.type 列表視圖中。

提示:你可以在這里找到一個例子: 模型視圖。

屬性和選項?

詳細介紹所有可用于微調視圖外觀的功能將是不切實際的。因此,我們將只介紹最常見的功能。

表單?

注解

目標 :本節結束時,屬性表單視圖將具有以下內容:

  • 按鈕和字段的條件顯示

  • 標簽顏色

帶有裝飾的表單視圖

在我們的房地產模塊中,我們想要修改一些字段的行為。例如,我們不希望能夠從表單視圖中創建或編輯屬性類型。相反,我們希望在它們適當的菜單中處理這些類型。我們還想給標簽添加顏色。為了添加這些行為自定義,我們可以向幾個字段小部件添加 options 屬性。

Exercise

添加小部件選項。

  • property_type_id 字段中添加適當的選項,以防止從屬性表單視圖創建和編輯屬性類型。有關更多信息,請參閱: Many2one widget documentation 。

  • 添加以下字段:

模型

字段

類型

estate.property.tag

顏色

整數

然后在 tag_ids 字段中添加適當的選項,以在標簽上添加顏色選擇器。更多信息請參閱 FieldMany2ManyTags widget documentation 。

第六章:終于有一些界面可以玩了 中,我們看到保留字段用于特定的行為。例如, active 字段用于自動過濾非活動記錄。我們也將 state 添加為保留字段?,F在是使用它的時候了! state 字段與視圖中的 states 屬性結合使用,有條件地顯示按鈕。

Exercise

添加按鈕的條件顯示。

使用 states 屬性按條件顯示標題按鈕,如本節的 目標 所示(請注意當狀態被修改時,“已售出”和“取消”按鈕會發生變化)。

提示:不要猶豫,在Odoo XML文件中搜索 states= 以獲取一些示例。

更一般地說,可以通過 attrs 屬性基于其他字段的值使字段變為 invisible 、 readonlyrequired 。請注意, invisible 也可以應用于視圖中的其他元素,如 buttongroup 。

attrs 是一個字典,以屬性為鍵,以域為值。域給出了屬性適用的條件。例如:

<form>
    <field name="description" attrs="{'invisible': [('is_partner', '=', False)]}"/>
    <field name="is_partner" invisible="1"/>
</form>

這意味著當 is_partnerFalse 時, description 字段是不可見的。需要注意的是,在 attrs 中使用的字段 必須 存在于視圖中。如果它不應該顯示給用戶,我們可以使用 invisible 屬性來隱藏它。

Exercise

使用 attrs 。

  • 當沒有花園時,在“estate.property”表單視圖中使花園區域和方向不可見。

  • 一旦報價狀態設置,使“接受”和“拒絕”按鈕不可見。

  • 當物業狀態為’Offer Accepted’、’Sold’或’Canceled’時,不允許添加報價。要實現此功能,請使用 readonly attrs 。

警告

在視圖中使用(條件) readonly 屬性可以防止數據輸入錯誤,但請記住它不提供任何安全級別!沒有進行服務器端檢查,因此始終可以通過RPC調用在字段上寫入。

列表?

注解

目標 :本節結束時,屬性和報價列表視圖應具有顏色裝飾。此外,報價和標簽將可以直接在列表中進行編輯,并且可用日期將默認隱藏。

帶裝飾和可選字段的列表視圖 可編輯列表

當模型只有少量字段時,直接通過列表視圖編輯記錄而無需打開表單視圖可能會很有用。在房地產示例中,添加報價或創建新標簽時無需打開表單視圖。這可以通過 editable 屬性實現。

Exercise

使列表視圖可編輯。

使 estate.property.offerestate.property.tag 的列表視圖可編輯。

另一方面,當模型有很多字段時,很容易在列表視圖中添加太多字段,使其變得不清晰。另一種方法是添加字段,但使它們可選隱藏。這可以通過“optional”屬性實現。

Exercise

將字段設為可選。

在“estate.property”列表視圖中,將字段“date_availability”默認設置為可選和隱藏。

最后,顏色代碼對于強調記錄非常有用。例如,在房地產模塊中,我們希望以紅色顯示被拒絕的報價,以綠色顯示被接受的報價。這可以通過 decoration-{$name} 屬性實現(請參見 字段小部件 獲取完整列表):

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

is_partnerTrue 時,記錄將以綠色顯示。

Exercise

添加一些裝飾品。

estate.property 列表視圖中:

  • 已收到報價的房產標記為綠色

  • 已接受報價的房產為綠色和粗體

  • 已售出的物業已靜音

estate.property.offer 列表視圖中:

  • 拒絕的報價是紅色的

  • 已接受的報價為綠色

  • 該狀態不應再可見

小費:

  • 請記住, 所有 用于屬性的字段都必須在視圖中!

  • 如果您想測試“已收到報價”和“已接受報價”狀態的顏色,請在表單視圖中添加該字段并手動更改它(稍后我們將實現業務邏輯)。

狀態按鈕?

注解

目標 :本節結束時,屬性類型表單視圖上將有一個狀態按鈕,當單擊該按鈕時,它將顯示與給定類型的屬性相關的所有報價列表。

統計按鈕

如果您已經在Odoo中使用了一些功能模塊,您可能已經遇到了“狀態按鈕”。這些按鈕顯示在表單視圖的右上方,并快速訪問鏈接文檔。在我們的房地產模塊中,我們希望有一個快速鏈接到與給定物業類型相關的報價,如本節的 目標 所示。

在本教程的這個階段,我們已經學習了大部分的概念。然而,并沒有一種單一的解決方案,如果您不知道從哪里開始,仍然可能會感到困惑。我們將在練習中描述一種逐步解決方案。通過查找“oe_stat_button”在Odoo代碼庫中的一些示例,也可能會有所幫助。

以下練習可能比之前的練習更難,因為它假設您能夠自己在源代碼中搜索示例。如果您卡住了,附近可能有人可以幫助您 ;-)

本練習介紹了 相關字段 的概念。最簡單的理解方法是將其視為計算字段的特定情況。下面是 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_idsoffer_count 添加到視圖中。下一步是在單擊統計按鈕時顯示列表。

  • estate.property.type 上創建一個指向 estate.property.offer 操作的狀態按鈕。這意味著你應該使用 type="action" 屬性(如果需要回顧,請返回到 第十章:準備好行動了嗎? 的結尾)。

此時,單擊狀態按鈕應該顯示所有報價。我們仍然需要過濾掉這些報價。

  • estate.property.offer 操作中,添加一個域,將 property_type_id 定義為等于 active_id (即當前記錄, 這里有一個例子

看起來不錯嗎?如果不是,不用擔心, 下一章 不需要狀態按鈕 ;-)