第11章:添加糖粉

从商业角度来看,我们的房地产模块现在变得有意义。我们创建了 specific views,添加了几个 action buttons 和 constraints。然而我们的用户界面仍然有点粗糙。我们想向列表视图添加一些颜色,并使一些字段和按钮有条件地消失。例如,当财产被出售或取消时,“已出售”和“取消”按钮应该消失,因为此时不再允许更改状态。

本章涵盖了可以在视图中执行的操作的一小部分。请随时阅读参考文档以获得更完整的概述。

参考:与本章相关的文档可以在:doc:../../reference/user_interface/view_records`和:doc:../../reference/user_interface/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">
        <list>
            <field name="field_1"/>
            <field name="field_2"/>
        </list>
    </field>
</form>

在 test_model 的表单视图中,我们为 test_model_line 定义了一个特定的列表视图,其中包含字段“field_1` and ``field_2`”。

可以找到一个示例 here。

Exercise

添加内联列表视图。

  • 添加“One2many` field property_ids to the ``estate.property.type`”模型。

  • 在“estate.property.type”表单视图中添加字段,如本节的 目标 中所述。

小部件

参考:与本节相关的文档可以在:ref:`reference/js/widgets`中找到。

注解

目标:在本节末尾,应使用特定的小部件显示属性的状态:

状态栏小部件

显示四种状态:New、Offer Received、Offer Accepted 和 Sold。

每当我们向模型添加字段时,我们(几乎)永远不必担心这些字段在用户界面中的外观。例如,为“Date` field and a ``One2many`”字段提供日期选择器,并自动显示为列表。 Odoo 根据字段类型选择正确的“小部件”。

然而,在某些情况下,我们想要一个字段的特定表示,这可以通过``widget`` attribute. We already used it for the tag_ids field when we used the ``widget=”many2many_tags”``属性来完成。如果我们没有使用它,那么该字段将显示为列表。

每个字段类型都有一组小部件,可用于微调其显示。有些小部件还带有额外的选项。详细列表可在 领域 中找到。

Exercise

使用状态栏小部件。

使用“statusbar` widget in order to display the state of the ``estate.property`”,如本节的 目标 中所述。

提示:可以找到一个简单的示例 here。

警告

同一字段在视图中多次出现

仅将字段添加到列表或表单视图**一次**。不支持多次添加。

列表顺序

参考:与本节相关的文档可以在:ref:`reference/orm/models`中找到。

注解

目标:在本节末尾,所有列表都应默认按确定的顺序显示。可以手动订购属性类型。

在前面的练习中,我们创建了几个列表视图。但是,我们从未指定默认情况下必须按哪种顺序列出记录。这对于许多业务案例来说是非常重要的事情。例如,在我们的房地产模块中,我们希望在列表顶部显示最高报价。

模型

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()

我们的记录按降序“id”排序,这意味着最高的排在前面。

Exercise

添加型号订购。

在其对应的模型中定义以下命令:

模型

命令

estate.property

降序 ID

estate.property.offer

降价价格

estate.property.tag

姓名

estate.property.type

姓名

看法

可以在型号级别订购。这样做的优点是在检索记录列表的任何地方都具有一致的顺序。但是,由于“default_order` attribute (example”,也可以直接在视图中定义特定顺序。

手动的

模型和视图排序都在对记录进行排序时提供了灵活性,但我们仍然需要涵盖一种情况:手动排序。用户可能希望根据业务逻辑对记录进行排序。例如,在我们的房地产模块中,我们希望手动对房产类型进行排序。将最常用的类型显示在列表顶部确实很有用。如果我们的房产中介主要销售房屋,那么将“House”出现在“Apartment”之前会更方便。

为此,需要一个``sequence`` field is used in combination with the handle widget. Obviously the sequence field must be the first field in the ``_order``属性。

Exercise

添加手动订购。

  • 添加以下字段:

模型

场地

类型

estate.property.type

顺序

整数

  • 使用正确的小部件将序列添加到“estate.property.type”列表视图中。

提示:您可以在此处找到示例:model 和 view。

属性和选项

详细说明允许微调视图外观的所有可用功能是令人望而却步的。因此,我们将坚持使用最常见的。

形式

注解

目标:在本节末尾,属性表单视图将具有:

  • 按钮和字段的条件显示

  • 标签颜色

带喷洒的表单视图

在我们的房地产模块中,我们想要修改某些字段的行为。例如,我们不希望能够从表单视图创建或编辑属性类型。相反,我们希望在适当的菜单中处理这些类型。我们还想给标签指定颜色。为了添加这些行为自定义,我们可以将“options”属性添加到多个字段小部件。

Exercise

添加小部件选项。

  • 将适当的选项添加到“property_type_id”字段,以防止从属性表单视图创建和编辑属性类型。请查看 Many2one widget documentation 了解更多信息。

  • 添加以下字段:

模型

场地

类型

estate.property.tag

颜色

整数

然后将适当的选项添加到“tag_ids”字段,以在标签上添加颜色选择器。请查看 FieldMany2ManyTags widget documentation 了解更多信息。

在 第 5 章:最后,一些可以使用的 UI 中,我们看到保留字段用于特定行为。例如,视图中的``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``属性用于有条件地显示按钮。

Exercise

添加按钮的条件显示。

使用 invisible 属性有条件地显示标题按钮,如本节的 目标 中所述(请注意状态修改时“已售出”和“取消”按钮如何变化)。

提示:请随时在 Odoo XML 文件中搜索 invisible= 来获取一些示例。

更一般地,可以创建一个字段“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 和 required 可以使用任何 Python 表达式作为值。该表达式给出了属性应用的条件。例如:

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

这意味着``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``属性隐藏它。

Exercise

使用``invisible``。

  • 当没有花园时,使花园面积和方向在“estate.property”表单视图中不可见。

  • 设置要约状态后,使“接受”和“拒绝”按钮不可见。

  • 当房产状态为“已接受报价”、“已售出”或“已取消”时,不允许添加报价。为此,请使用“readonly”属性。

警告

在视图中使用(条件)“readonly”属性对于防止数据输入错误很有用,但请记住,它不提供任何级别的安全性!服务器端没有进行任何检查,因此始终可以通过 RPC 调用在字段上写入。

列表

注解

目标:在本节末尾,属性和优惠列表视图应具有颜色装饰。此外,优惠和标签可以直接在列表中编辑,并且默认情况下会隐藏可用日期。

带有装饰和可选字段的列表视图 可编辑列表

当模型只有几个字段时,直接通过列表视图编辑记录而不需要打开表单视图会很有用。在房地产示例中,无需打开表单视图来添加报价或创建新标签。这可以通过“editable”属性来实现。

Exercise

使列表视图可编辑。

使“estate.property.offer` and ``estate.property.tag`”列表视图可编辑。

另一方面,当模型有很多字段时,可能会很容易在列表视图中添加太多字段并使其不清楚。另一种方法是添加字段,但可以选择隐藏它们。这可以通过“optional”属性来实现。

Exercise

将字段设置为可选。

使字段“date_availability` on the ``estate.property`”列表视图可选并默认隐藏。

最后,颜色代码对于在视觉上强调记录很有用。例如,在房地产模块中,我们希望以红色显示拒绝的报价,以绿色显示接受的报价。这可以通过“decoration-{$name}”属性来实现(完整列表请参见 领域):

<list decoration-success="is_partner==True">
    <field name="name"/>
</list>

包含“is_partner` is ``True`”的记录将显示为绿色。

Exercise

添加一些装饰。

在“estate.property”列表视图上:

  • 收到报价的房产是绿色的

  • 接受报价的房产是绿色且大胆的

  • 出售的房产表现平平

在“estate.property.offer”列表视图上:

  • 拒绝的优惠呈红色

  • 已接受的报价为绿色

  • 状态不应该再可见

尖端:

  • 请记住,属性中使用的**所有**字段都必须位于视图中!

  • 如果您想测试“Offer Received”和“Offer Accepted”状态的颜色,请在表单视图中添加该字段并手动更改它(我们稍后将为此实现业务逻辑)。

统计按钮

注解

目标:在本节的末尾,属性类型表单视图上将有一个统计按钮,单击该按钮时会显示与给定类型的属性相关的所有报价的列表。

统计按钮

如果您已经使用过 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 to estate.property.offer. We can define it as a related field on property_id.property_type_id 并将其设置为已存储。

由于此字段,报价在创建时将链接到房产类型。您可以将该字段添加到报价列表视图中以确保其正常工作。

  • 添加字段“offer_ids` to ``estate.property.type`”,它是上一步中定义的字段的 One2many 逆。

  • 添加字段“offer_count` to estate.property.type. It is a computed field that counts the number of offers for a given property type (use ``offer_ids`”来执行此操作)。

此时,您已掌握了了解有多少报价链接到某种房产类型所需的所有信息。如有疑问,请将 offer_ids and offer_count 直接添加到视图中。下一步是在单击统计按钮时显示列表。

  • 在“estate.property.type` pointing to the estate.property.offer action. This means you should use the ``type=”action””属性上创建一个统计按钮(如果需要复习,请返回到 :doc:`09_actions 的末尾)。

此时,单击统计按钮应显示所有报价。我们仍然需要过滤掉报价。

看起来不错吗?如果没有,别担心,next chapter 不需要统计按钮;-)