第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`fieldproperty_idsto 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
添加型号订购。
在其对应的模型中定义以下命令:
模型 |
命令 |
|---|---|
|
降序 ID |
|
降价价格 |
|
姓名 |
|
姓名 |
看法¶
可以在型号级别订购。这样做的优点是在检索记录列表的任何地方都具有一致的顺序。但是,由于“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``属性。
属性和选项¶
详细说明允许微调视图外观的所有可用功能是令人望而却步的。因此,我们将坚持使用最常见的。
形式¶
注解
目标:在本节末尾,属性表单视图将具有:
按钮和字段的条件显示
标签颜色
在我们的房地产模块中,我们想要修改某些字段的行为。例如,我们不希望能够从表单视图创建或编辑属性类型。相反,我们希望在适当的菜单中处理这些类型。我们还想给标签指定颜色。为了添加这些行为自定义,我们可以将“options”属性添加到多个字段小部件。
Exercise
添加小部件选项。
将适当的选项添加到“
property_type_id”字段,以防止从属性表单视图创建和编辑属性类型。请查看 Many2one widget documentation 了解更多信息。添加以下字段:
模型 |
场地 |
类型 |
|---|---|---|
|
颜色 |
整数 |
然后将适当的选项添加到“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”属性来实现。
另一方面,当模型有很多字段时,可能会很容易在列表视图中添加太多字段并使其不清楚。另一种方法是添加字段,但可以选择隐藏它们。这可以通过“optional”属性来实现。
最后,颜色代码对于在视觉上强调记录很有用。例如,在房地产模块中,我们希望以红色显示拒绝的报价,以绿色显示接受的报价。这可以通过“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”状态的颜色,请在表单视图中添加该字段并手动更改它(我们稍后将为此实现业务逻辑)。
搜索¶
参考:与本节相关的文档可以在 搜索 和 搜索默认值 中找到。
注解
目标:在本节结束时,将默认过滤可用属性,并且在居住面积上搜索将返回面积大于给定数字的结果。
最后但并非最不重要的一点是,我们希望在搜索时应用一些调整。首先,我们希望在访问属性时默认应用“可用”过滤器。为了实现这一点,我们需要使用“search_default_{$name}` action context, where ``{$name}`”作为过滤器名称。这意味着我们可以定义在操作级别默认激活哪些过滤器。
以下是 action 及其 corresponding filter 的示例。
Exercise
添加默认过滤器。
在“estate.property”操作中默认选择“可用”过滤器。
我们模块的另一个有用的改进是能够按居住区域进行有效搜索。在实践中,用户将希望搜索“至少”给定区域的属性。期望用户想要找到确切居住区域的房产是不现实的。总是可以进行自定义搜索,但这很不方便。
搜索视图 <field> elements can have a filter_domain that overrides the domain generated for searching on the given field. In the given domain, self represents the value entered by the user. In the example below, it is used to search on both name and description 字段。
<search string="Test">
<field name="description" string="Name and description"
filter_domain="['|', ('name', 'ilike', self), ('description', 'ilike', self)]"/>
</search>
Exercise
更改居住区搜索。
将“filter_domain”添加到生活区域以包含面积等于或大于给定值的属性。