原文:Odoo 18 官方开发教程“Server framework 101”第 9 章。本文尽量保留原文结构、代码、练习与图片,仅进行中文翻译,并在文末增加“老赵解读”。
第 9 章:准备好采取行动了吗?
到目前为止,我们主要通过声明字段和视图来构建我们的模块。我们刚刚介绍了业务
上一章 中的逻辑感谢
计算了字段和 onchanges。在任何真实的业务场景中,我们都希望链接一些业务
逻辑到操作按钮。在我们的房地产示例中,我们希望能够:
- 取消或将房产设置为已售出
- 接受或拒绝报价
有人可能会说我们已经可以通过手动更改状态来完成这些事情,但是
这实在不太方便。此外,我们想添加一些额外的处理:当报价是
接受我们想要为房产设置售价和买家。
对象类型
参考:与该主题相关的文档可以在以下位置找到
行动 和 错误管理。
说明
目标: 在本节末尾:
- 您应该能够取消或将房产设置为已售:
已取消的房产无法出售,已出售的房产也无法取消。为了
为清楚起见,state字段已添加到视图上。
- 您应该能够接受或拒绝报价:
- 一旦报价被接受,应设置售价和买家:
在我们的房地产模块中,我们希望将业务逻辑与一些按钮链接起来。最常见的方法是
这样做是为了:
- 在视图中添加一个按钮,例如在视图的
header中:
<form>
<header>
<button name="action_do_something" type="object" string="Do Something"/>
</header>
<sheet>
<field name="name"/>
</sheet>
</form>
- 并将此按钮链接到业务逻辑:
from odoo import fields, models
class TestAction(models.Model):
_name = "test.action"
name = fields.Char()
def action_do_something(self):
for record in self:
record.name = "Something"
return True
通过将 type="object" 分配给我们的按钮,Odoo 框架将执行一个 Python 方法
在给定的模型上使用 name="action_do_something"。
要注意的第一个重要细节是我们的方法名称没有以下划线前缀
(_)。这使得我们的方法成为 公开的 方法,可以直接从 Odoo 调用
接口(通过 RPC 调用)。到目前为止,我们创建的所有方法(compute、onchange)都被调用
在内部,所以我们使用 私人的 以下划线前缀的方法。你应该始终定义你的
方法作为私有方法,除非它们需要从用户界面调用。
另请注意,我们在 self 上循环。始终假设一个方法可以在多个记录上调用;这是
更好的可重用性。
最后,公共方法应该始终返回一些内容,以便可以通过 XML-RPC 调用它。
如有疑问,只需 return True。
Odoo 源代码中有数百个示例。一个例子是这样的
视图中的按钮
和它的
对应的Python方法
练习
取消并将房产设置为已售出。
- 将“取消”和“已售出”按钮添加到
estate.property模型。取消的房产
无法设定为已售出,且已售出的房产无法取消。请参考第一张图片 目标 为了达到预期的结果。
提示:为了引发错误,您可以使用 用户错误
功能。 Odoo 源代码中有很多示例;-)
- 将按钮“接受”和“拒绝”添加到estate.property.offer模型。请参阅第二张图片 目标 为了达到预期的结果。
提示:要使用图标作为按钮,请查看
在这个例子中。
- 当报价被接受时,设置相应房产的买家和售价。参考第三张图 目标 为了达到预期的结果。
注意:在现实生活中,对于给定的房产,只能接受一个报价!
动作类型
在 第 5 章:最后,一些可以使用的 UI 中,我们创建了一个链接到菜单的操作。你
可能想知道是否可以将操作链接到按钮。好消息,确实如此!一种方法可以做到这一点
是:
<button type="action" name="%(test.test_model_action)d" string="My Action"/>
我们使用 type="action" 并引用 name 中的 外部标识符。
在 下一章 中,我们将了解如何防止
在 Odoo 中编码不正确的数据。
老赵解读
业务动作把“记录数据”推进到“执行流程”。按钮方法通常会同时修改多个字段或关联记录,因此必须明确允许的前置状态、执行后的结果以及重复点击时的行为。
真实项目中建议把状态转换视为受约束的业务命令:先校验,再一次性写入,并在必要时记录操作者和时间。这样才能避免流程被直接写字段绕过,也便于后续审计。