第 9 章:准备好迎接一些操作了吗?

到目前为止,我们主要是通过声明字段和视图来构建模块。在 上一章 中,我们刚刚通过计算字段(computed fields)和变更(onchanges)引入了业务逻辑。在任何实际业务场景中,我们都希望将一些业务逻辑与操作按钮关联起来。在我们的房地产示例中,我们希望能够:

  • 取消或将房产标记为已售

  • 接受或拒绝报价

有人可能会说,我们已经可以通过手动更改状态来完成这些操作,但这并不方便。此外,我们希望添加一些额外的处理:当报价被接受时,我们需要设置房产的销售价格和买家信息。

对象类型(Object Type)

参考:与此主题相关的文档可以在 操作错误管理 中找到。

注解

目标:在本节结束时:

  • 您应该能够取消或将房产标记为已售:

取消并标记为已售

已取消的房产无法出售,而已售的房产无法取消。为了清晰起见, 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 方法。

需要注意的第一个重要细节是,我们的方法名称没有以下划线( _ )开头。这使得我们的方法成为一个 公共方法(public method),可以直接从 Odoo 界面调用(通过 RPC 调用)。在此之前,我们创建的所有方法(计算字段、变更)都是内部调用的,因此我们使用了以下划线开头的 私有方法(private method)。除非方法需要从用户界面调用,否则您应始终将其定义为私有方法。

另请注意,我们在 self 上进行循环。始终假设方法可能作用于多条记录;这有助于提高可重用性。

最后,公共方法应始终返回某些内容,以便可以通过 XML-RPC 调用。如果不确定,只需 return True

在 Odoo 源代码中有数百个示例。其中一个例子是这个 视图中的按钮 及其 对应的 Python 方法

Exercise

取消并将属性标记为已售出。

  • estate.property 模型中添加“取消”和“已售出”按钮。已取消的属性不能标记为已售出,而已售出的属性不能取消。

    请参考 目标 的第一张图片以了解预期结果。

    提示:为了引发错误,您可以使用 UserError 函数。Odoo 源代码中有许多示例 ;-)

  • estate.property.offer 模型中添加“接受”和“拒绝”按钮。

    请参考 目标 的第二张图片以了解预期结果。

    提示:要将图标用作按钮,请查看 此示例

  • 当报价被接受时,为相应的属性设置买家和销售价格。

    请参考 目标 的第三张图片以了解预期结果。

    请注意:在现实生活中,对于给定的属性,只能接受一个报价!

动作类型(Action Type)

第 5 章:终于,可以玩转一些用户界面(UI)了 中,我们创建了一个与菜单关联的动作。您可能想知道是否可以将动作与按钮关联。好消息是可以!一种方法是:

<button type="action" name="%(test.test_model_action)d" string="My Action"/>

我们使用 type="action" 并在 name 中引用 external identifier

下一章 中,我们将了解如何防止在 Odoo 中编码错误数据。