第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框架将在给定的模型上执行一个名为 name="action_do_something"
的Python方法。
首先要注意的重要细节是,我们的方法名没有前缀下划线( _
)。这使得我们的方法成为一个 公共 方法,可以直接从Odoo界面调用(通过RPC调用)。到目前为止,我们创建的所有方法(compute,onchange)都是在内部调用的,所以我们使用了以下划线为前缀的 私有 方法。除非需要从用户界面调用,否则您应该始终将方法定义为私有方法。
同时请注意我们在 self
上进行循环。始终假设一个方法可以在多个记录上调用;这样更有利于可重用性。
最后,一个公共方法应该始终返回一些内容,以便可以通过XML-RPC进行调用。如果不确定,只需 return True
。
在Odoo源代码中有数百个示例。一个示例是这个 视图中的按钮 <https://github.com/odoo/odoo/blob/cd9af815ba591935cda367d33a1d090f248dd18d/addons/crm/views/crm_lead_views.xml#L9-L11>
__和它的 对应的Python方法 <https://github.com/odoo/odoo/blob/cd9af815ba591935cda367d33a1d090f248dd18d/addons/crm/models/crm_lead.py#L746-L760>
__
Exercise
取消并将属性标记为已售。
在
estate.property
模型中添加 ‘取消’ 和 ‘已售’ 按钮。已取消的房产不能设置为已售,已售的房产不能取消。请参考 目标 的第一张图片以获取预期结果。
提示:为了引发错误,您可以使用 UserError 函数。在Odoo源代码中有很多示例;-)
在
estate.property.offer
模型中添加按钮 ‘Accept’ 和 ‘Refuse’。请参考 目标 的第二张图片以获取预期结果。
提示:要将图标用作按钮,请查看 此示例.
当一个报价被接受时,为相应的房产设置买家和销售价格。
请参考 目标 的第三张图片以获取预期结果。
注意:在现实生活中,对于一处房产,只能接受一个报价!
操作类型¶
在 第5章:终于,有了可以操作的UI 中,我们创建了一个与菜单链接的操作。你可能想知道是否可以将操作链接到按钮。好消息是,这是可以的!一种实现方式是:
<button type="action" name="%(test.test_model_action)d" string="My Action"/>
我们使用 type="action"
,并在 name
中引用 外部标识符。
在 下一章 中,我们将了解如何防止在 Odoo 中编码错误的数据。