Odoo开发求助:@api.depends未触发跨模型字段更新
解决Odoo中@api.depends未触发的问题
嘿,作为Odoo开发新手遇到这种依赖触发问题很常见,我来帮你梳理下可能的原因和解决办法~
首先得明确你的需求:当marketplace.marketplace的formula字段变更时,更新关联的marketplace.marketplaceinfo的recommanded_price。这里分两种场景来处理:
场景1:recommanded_price是计算字段(实时计算)
如果recommanded_price是基于主模型formula动态计算的,你需要在**子模型(marketplaceinfo)**中定义计算字段,并正确设置依赖关系。之前可能错把@api.depends写在了主模型里,导致没触发。
正确代码示例:
from odoo import models, fields, api class MarketplaceInfo(models.Model): _name = 'marketplace.marketplaceinfo' _description = 'Marketplace Info' # 确保这里的many2one字段正确关联到主模型 mkp_id = fields.Many2one('marketplace.marketplace', string='Marketplace', required=True) cost = fields.Float('Cost') # 假设你需要用这个字段计算价格 recommanded_price = fields.Float( 'Recommended Price', compute='_compute_recommanded_price', store=True # 如果需要把计算值存到数据库,加上这个参数 ) @api.depends('mkp_id.formula') def _compute_recommanded_price(self): for info in self: if not info.mkp_id.formula: info.recommanded_price = 0.0 continue # 安全解析formula,建议限制可使用的变量和函数 safe_namespace = { 'cost': info.cost, 'min': min, 'max': max, # 只允许必要的数学运算,避免安全风险 } try: info.recommanded_price = eval(info.mkp_id.formula, safe_namespace) except Exception as e: info.recommanded_price = 0.0 # 可以在这里加日志记录错误 self.env.user.notify_danger(message=f"Formula解析错误: {str(e)}")
关键注意点:
@api.depends要写在子模型的计算方法上,依赖路径是关联字段.主模型字段(即mkp_id.formula)- 如果设置了
store=True,Odoo会自动在主模型formula变更时更新子记录的存储值
场景2:recommanded_price是普通字段,需要主动更新
如果recommanded_price是普通存储字段,需要在主模型formula变更时主动批量更新子记录,这时候@api.depends不适用,应该用@api.onchange(前端编辑时触发)或者重载write方法(后台/批量修改时触发)。
方法1:前端编辑时实时更新(@api.onchange)
class Marketplace(models.Model): _name = 'marketplace.marketplace' _description = 'Marketplace' formula = fields.Char('Formula') product_ids = fields.One2many('marketplace.marketplaceinfo', 'mkp_id', string='Products') @api.onchange('formula') def _onchange_formula_update_prices(self): if not self.formula: for product in self.product_ids: product.recommanded_price = 0.0 return safe_namespace = {'cost': None} for product in self.product_ids: safe_namespace['cost'] = product.cost try: product.recommanded_price = eval(self.formula, safe_namespace) except Exception as e: product.recommanded_price = 0.0 self.env.user.notify_danger(message=f"更新{product.name}价格失败: {str(e)}")
方法2:后台/批量修改时触发(重载write方法)
class Marketplace(models.Model): _name = 'marketplace.marketplace' _description = 'Marketplace' formula = fields.Char('Formula') product_ids = fields.One2many('marketplace.marketplaceinfo', 'mkp_id', string='Products') def write(self, vals): # 先执行父类的write操作,更新formula result = super().write(vals) # 如果formula字段被修改,更新所有关联子记录 if 'formula' in vals: safe_namespace = {'cost': None} for mkp in self: for product in mkp.product_ids: safe_namespace['cost'] = product.cost try: product.recommanded_price = eval(mkp.formula, safe_namespace) except Exception as e: product.recommanded_price = 0.0 self.env.user.notify_danger(message=f"更新{product.name}价格失败: {str(e)}") return result
常见排查点
- 检查关联字段是否正确:子模型的
many2one字段(比如mkp_id)是否正确关联到主模型,字段名是否拼写错误 - 依赖路径是否正确:如果用计算字段,
@api.depends里的路径必须是关联字段.主模型字段,不能只写formula - 安全风险:直接使用
eval执行用户输入的公式有安全隐患,一定要限制命名空间,只允许必要的变量和函数
内容的提问来源于stack exchange,提问作者meyou shizuka
相关产品推荐
相关产品推荐

