第8章:odoo @onchange与@depends装饰器异同

1. @onchange 装饰器

@onchange 是一种基于 用户界面(UI)的触发器,用于监听某些字段的值在前端界面中发生变化时,自动调用对应的方法。

关键特点

  1. 触发时机: 当用户在界面上修改某个字段的值并切换到其他字段时,触发 @onchange 方法。
  2. 仅作用于前端: @onchange 的结果不会存储到数据库,仅在当前的会话中生效。
  3. 实时反馈: 用于动态更新界面中的其他字段,例如计算值、设置默认值或更新界面状态。
  4. 不可用于业务规则: 因为其结果不存储到数据库,因此不能依赖 @onchange 实现持久化业务逻辑。

示例代码

from odoo import models, fields, api

class SaleOrder(models.Model):
    _name = 'sale.order'

    product_id = fields.Many2one('product.product', string="Product")
    unit_price = fields.Float(string="Unit Price")
    quantity = fields.Integer(string="Quantity")
    total_price = fields.Float(string="Total Price", readonly=True)

    @api.onchange('product_id', 'quantity')
    def _onchange_calculate_price(self):
        if self.product_id and self.quantity:
            self.unit_price = self.product_id.list_price
            self.total_price = self.unit_price * self.quantity
        else:
            self.unit_price = 0.0
            self.total_price = 0.0


使用场景

  • 根据用户选择的值动态更新其他字段的显示值。
  • 动态调整字段的只读、必填或可见状态。
  • 在界面上执行实时计算,如金额总计。

2. @depends 装饰器

@depends 是用于 后端计算字段 的触发器,用于声明一个字段的值依赖于其他字段的变更。

关键特点

  1. 触发时机: 当被声明依赖的字段值发生变化时,自动重新计算目标字段。
  2. 作用于后端: 其逻辑会影响数据库中的值,因为它通常与计算字段一起使用。
  3. 自动触发: 不需要用户交互,当依赖字段的值通过任何方式(UI 或后端代码)被修改时,都会触发重新计算。
  4. 适合复杂业务逻辑: 通常用于处理需要持久化的计算规则。

示例代码

from odoo import models, fields, api

class SaleOrder(models.Model):
    _name = 'sale.order'

    product_id = fields.Many2one('product.product', string="Product")
    unit_price = fields.Float(string="Unit Price", compute="_compute_price", store=True)
    quantity = fields.Integer(string="Quantity")
    total_price = fields.Float(string="Total Price", compute="_compute_price", store=True)

    @api.depends('product_id', 'quantity')
    def _compute_price(self):
        for record in self:
            if record.product_id and record.quantity:
                record.unit_price = record.product_id.list_price
                record.total_price = record.unit_price * record.quantity
            else:
                record.unit_price = 0.0
                record.total_price = 0.0


使用场景

  • 自动计算字段的值,并将其存储到数据库中。
  • 用于复杂的业务逻辑或规则需要被持久化的场景。
  • 构建报表或筛选器时依赖的字段计算。

3. @onchange 和 @depends 的对比

特性@onchange@depends
触发机制用户在界面中修改字段值时触发依赖字段的值发生变化时自动触发
触发范围仅限前端,结果不存储在数据库作用于后端,计算结果可以存储到数据库
结果是否持久化不会持久化,仅在会话中有效会持久化,计算结果存储到数据库中
适用场景实时更新界面、动态调整字段状态后端字段计算、持久化业务逻辑
常用装饰器组合单独使用,与 @api.onchange 绑定通常与 @api.depends 和 compute 字段搭配使用
使用复杂性适合简单的动态调整或实时显示适合复杂的业务逻辑和持久化计算

4. 总结

  • @onchange: 是纯前端的,仅仅增强体验,但不能依赖,因为后端的入口会直接无视他
  • @depends: 前后端都支持,相对靠谱,但又不能完全替代onchange的,因为计算的是只读的,onchange是针对可写的预设值而已。
  • 选择原则:
    • 如果结果仅用于界面显示或动态交互,选择 @onchange。
    • 如果需要持久化计算结果并用于后续操作,选择 @depends。


5.扩展:可以将@onchange 和@depends 联合使用

在一些场景下,这两个可以结合使用,以实现更强大的逻辑处理能力。例如:

  • @onchange 用于界面中的实时更新。
  • @depends 用于后端的持久化计算。

示例代码

from odoo import models, fields, api

class SaleOrder(models.Model):
    _name = 'sale.order'

    product_id = fields.Many2one('product.product', string="Product")
    unit_price = fields.Float(string="Unit Price", compute="_compute_price", store=True)
    quantity = fields.Integer(string="Quantity")
    total_price = fields.Float(string="Total Price", compute="_compute_price", store=True)

    @api.depends('product_id', 'quantity')
    def _compute_price(self):
        for record in self:
            if record.product_id and record.quantity:
                record.unit_price = record.product_id.list_price
                record.total_price = record.unit_price * record.quantity
            else:
                record.unit_price = 0.0
                record.total_price = 0.0

    @api.onchange('product_id')
    def _onchange_product_id(self):
        if self.product_id:
            self.unit_price = self.product_id.list_price

徐朋朋 2024年11月19日
分析这篇文章

存档
登录 留下评论
第8章:计算域和onchanges