第 11 章:添加点缀¶
我们的房地产模块从商业角度来看现在已初具雏形。我们创建了 特定视图 ,添加了多个 操作按钮 和 约束条件 。然而,我们的用户界面仍然有些粗糙。我们希望为列表视图添加一些颜色,并让某些字段和按钮根据条件隐藏。例如,“已售出”和“取消”按钮在房产状态为已售或已取消时应消失,因为此时不再允许更改状态。
本章仅涵盖视图功能的一小部分。如需更全面的概述,请随时查阅参考文档。
内联视图¶
注解
目标:在本节结束时,应在房产类型视图中添加特定的房产列表:

在房地产模块中,我们为房产添加了一个报价列表。我们只需通过以下方式添加字段 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
和 field_2
。
可以在此处找到示例: 这里 。
Exercise
添加内联列表视图。
向
estate.property.type
模型添加One2many
字段property_ids
。将字段添加到
estate.property.type
的表单视图中,如本节 目标 中所示。
部件¶
参考:与本节相关的文档可以在 字段 中找到。
注解
目标:在本节结束时,房产状态应使用特定的小部件显示:

显示四种状态:新建、收到报价、接受报价和已售出。
每当我们向模型添加字段时,几乎不需要担心这些字段在用户界面中的外观。例如, Date
字段会提供日期选择器,而 One2many
字段会自动显示为列表。Odoo 会根据字段类型选择合适的“小部件”。
然而,在某些情况下,我们需要特定的字段表示形式,这可以通过 widget
属性实现。我们已经在 tag_ids
字段中使用过它,当时我们使用了 widget="many2many_tags"
属性。如果我们没有使用它,那么该字段将显示为列表。
每种字段类型都有一组小部件,可用于微调其显示效果。一些小部件还支持额外选项。完整列表请参阅 字段 。
警告
在同一视图中多次出现相同字段
只能将字段 一次 添加到列表或表单视图中。不支持多次添加。
列表排序¶
参考:与本节相关的文档可以在 模型 中找到。
注解
目标:在本节结束时,所有列表应默认以确定性顺序显示。房产类型可以手动排序。
在之前的练习中,我们创建了多个列表视图。然而,我们从未指定记录的默认排序方式。这对于许多业务场景来说非常重要。例如,在我们的房地产模块中,我们可能希望将最高报价显示在列表顶部。
模型¶
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
添加模型排序。
在对应的模型中定义以下排序顺序:
模型 |
排序 |
---|---|
|
按 ID 降序 |
|
按价格降序 |
|
名称 |
|
名称 |
视图¶
可以在模型级别进行排序。这种方法的优点是无论在哪检索记录列表,排序都是一致的。然而,也可以通过视图中的 default_order
属性直接定义特定的排序( 示例 )。
手动¶
模型和视图排序都能在记录排序时提供灵活性,但还有一种情况需要覆盖:手动排序。用户可能希望根据业务逻辑对记录进行排序。例如,在我们的房地产模块中,我们可能希望手动对房产类型进行排序。让最常用的类型出现在列表顶部确实很有用。如果我们的房地产机构主要销售房屋,那么让“房屋”排在“公寓”之前会更方便。
为此,可以结合使用 sequence
字段和 handle
小部件。显然, sequence
字段必须是 _order
属性中的第一个字段。
属性与选项¶
详细说明所有可用于微调视图外观的功能将会非常繁琐。因此,我们将专注于最常见的功能。
表单¶
注解
目标:在本节结束时,房产表单视图将具有以下内容:
按钮和字段的条件显示
标签颜色

在我们的房地产模块中,我们希望修改某些字段的行为。例如,我们不希望通过表单视图创建或编辑房产类型。相反,我们期望在适当的菜单中管理类型。此外,我们还希望为标签添加颜色。为了实现这些行为定制,我们可以为多个字段小部件添加 options
属性。
Exercise
添加小部件选项。
为
property_type_id
字段添加适当的选项,以防止从属性表单视图中创建或编辑属性类型。请查看 Many2one 小部件文档 以获取更多信息。添加以下字段:
模型 |
字段 |
类型 |
---|---|---|
|
颜色 |
整数 |
然后为 tag_ids
字段添加适当的选项,以便在标签上添加颜色选择器。请查看 FieldMany2ManyTags 小部件文档 以获取更多信息。
在 第 5 章:终于,可以玩转一些用户界面(UI)了 中,我们看到保留字段被用于特定行为。例如,active
字段用于自动过滤掉非活动记录。我们也添加了 state
作为保留字段。现在是时候使用它了! state
字段可以与视图中的 invisible
属性结合使用,以实现按钮的条件显示。
Exercise
添加按钮的条件显示。
使用 invisible
属性按条件显示头部按钮,如本节 目标 中所示(注意当状态更改时,“已售出”和“取消”按钮如何变化)。
提示:不妨在 Odoo 的 XML 文件中搜索 invisible=
以找到一些示例。
更广泛地说,可以根据其他字段的值使字段变为 invisible
(不可见)、 readonly
(只读)或 required
(必填)。请注意, invisible
也可以应用于视图中的其他元素,例如 button
或 group
。
invisible
、 readonly
和 required
可以接受任何 Python 表达式作为值。该表达式指定了属性生效的条件。例如:
<form>
<field name="description" invisible="not is_partner"/>
</form>
这意味着当 is_partner
为 False
时, description
字段将不可见。需要注意的是,用于 invisible
的字段 必须 出现在视图中。如果它不应该向用户显示,我们可以使用 invisible
属性将其隐藏。
Exercise
使用 invisible
。
在
estate.property
表单视图中,当没有花园时,将花园面积和方向设置为不可见。一旦报价状态被设置,将“接受”和“拒绝”按钮设置为不可见。
当属性状态为“报价已接受”、“已售出”或“已取消”时,不允许添加报价。为此,请使用
readonly
属性。
警告
在视图中使用(条件性) readonly
属性可以有效防止数据输入错误,但请记住,它并不提供任何安全性!服务器端不会进行检查,因此始终可以通过 RPC 调用写入该字段。
列表¶
注解
目标:在本节结束时,房产和报价列表视图应具有颜色装饰。此外,报价和标签将可以直接在列表中编辑,而可用日期将默认隐藏。


当模型只有少量字段时,直接通过列表视图编辑记录而不打开表单视图可能会很有用。在房地产示例中,无需打开表单视图即可添加报价或创建新标签。这可以通过 editable
属性实现。
Exercise
使列表视图可编辑。
使 estate.property.offer
和 estate.property.tag
列表视图可编辑。
另一方面,当模型包含大量字段时,可能会倾向于在列表视图中添加过多字段,从而使视图变得不清晰。一种替代方法是添加这些字段,但使它们可以选择性隐藏。这可以通过使用 optional
属性实现。
Exercise
使字段可选。
使 estate.property
列表视图中的字段 date_availability
可选并默认隐藏。
最后,颜色代码对于视觉上突出显示记录非常有用。例如,在房地产模块中,我们希望将被拒绝的报价显示为红色,将接受的报价显示为绿色。这可以通过 decoration-{$name}
属性实现(完整列表请参见 字段 ):
<list decoration-success="is_partner==True">
<field name="name"/>
</list>
其中 is_partner
为 True
的记录将以绿色显示。
Exercise
添加一些装饰。
在 estate.property
列表视图中:
已收到报价的属性显示为绿色
已接受报价的属性显示为绿色且加粗
已售出的属性显示为低调(灰色)
在 estate.property.offer
列表视图中:
被拒绝的报价显示为红色
被接受的报价显示为绿色
状态字段应不再可见
提示:
请记住,属性中使用的所有字段都必须存在于视图中!
如果要测试“已收到报价”和“已接受报价”状态的颜色,请将字段添加到表单视图中并手动更改它(我们稍后会实现其业务逻辑)。
搜索¶
参考:与本节相关的文档可以在 搜索 和 搜索默认值 中找到。
注解
目标:在本节结束时,默认会对可用房产进行过滤,并且按居住面积搜索时返回面积大于给定值的结果。

最后但同样重要的是,我们在搜索时希望应用一些调整。首先,我们希望在访问房产时默认应用“可用”过滤器。为此,我们需要使用 search_default_{$name}
动作上下文,其中 {$name}
是过滤器名称。这意味着我们可以在动作级别定义哪些过滤器将默认激活。
Exercise
添加默认过滤器。
在 estate.property
操作中将“可用”过滤器设置为默认选中。
我们模块中的另一个有用改进是能够通过居住面积高效搜索。实际上,用户会希望搜索“至少”达到指定面积的房产。期望用户查找完全符合特定居住面积的房产是不现实的。虽然可以进行自定义搜索,但这并不方便。
搜索视图中的 <field>
元素可以具有一个 filter_domain
,用于覆盖为给定字段生成的域。在给定域中,self
表示用户输入的值。在下面的示例中,它用于同时搜索 name
和 description
字段。
<search string="Test">
<field name="description" string="Name and description"
filter_domain="['|', ('name', 'ilike', self), ('description', 'ilike', self)]"/>
</search>
Exercise
修改生活区域搜索。
为生活区域添加 filter_domain
,以包含面积等于或大于给定值的属性。