Odoo计算字段设置store=True后存储值为0且需加入自定义过滤的问题
核心问题根因
- 带存储的compute字段必须配置依赖触发规则:Odoo中
store=True的compute字段,必须通过@api.depends明确指定哪些字段变化时需要重算,否则仅会在记录创建时执行一次计算。你当前的逻辑里,刚创建楼宇时还没有绑定任何客户,算出来的客户数是0,后续不管绑定了多少客户,因为没有配置依赖,永远不会触发重算,数据库里的值就一直停留在初始的0。 - 字段类型不匹配:
customer_count被定义为Char类型存储整数计数,既不符合语义,也会导致筛选时的数值比较逻辑异常。 - 重复定义方法导致逻辑失效:模型中写了两个同名的
write方法,Python的类属性覆盖规则会让后定义的write完全覆盖前一个,之前写的区域、城市同步给客户的逻辑根本不会被执行。 - 原生SQL绕过ORM机制:直接拼接SQL字符串更新关联客户表的数据,既存在SQL注入风险,也不会触发Odoo的compute字段重算流程。
- 不带store的字段无法参与筛选:不设置
store=True的compute字段是界面加载时实时计算,不会存储到数据库,筛选逻辑需要在数据库层执行SQL查询,没有落库的字段自然不会出现在可筛选的字段列表里。
修复步骤
- 重构customer_count字段定义与计算逻辑
把字段类型改为整数,为compute方法添加正确的依赖声明,让关联客户变化时自动触发重算:# 字段定义 customer_count = fields.Integer( string='Customer Count', compute='_compute_customer_count', store=True # 落库后即可支持自定义筛选 ) # 计算方法 @api.depends('partner_ids') # 关联的客户列表变化时自动重算 def _compute_customer_count(self): for record in self: # 直接统计关联客户的数量,比单独写search_count效率更高 record.customer_count = len(record.partner_ids) - 合并重复的write方法逻辑
去掉重复的方法定义,把两个write里的业务逻辑合并到同一个方法中,改用ORM接口更新关联客户数据,避免原生SQL的风险:def write(self, vals): # 先执行原有的write逻辑 res = super(ResBuilding, self).write(vals) # 楼宇所属覆盖区域变化时,同步更新关联客户的居住区域 if vals.get('city_id'): related_partners = self.env['res.partner'].search([('building_id', 'in', self.ids)]) related_partners.write({'living_area': vals['city_id']}) # 楼宇所属行政区变化时,同步更新关联客户的所属区域 if vals.get('region_id'): related_partners = self.env['res.partner'].search([('building_id', 'in', self.ids)]) related_partners.write({'city_id': vals['region_id']}) return res - 优化位置坐标同步的SQL逻辑
修正原有拼接SQL的写法,改用参数化查询避免SQL注入:@api.depends('latitude', 'longitude') def on_change_location(self): for record in self: if record.latitude and record.longitude: # 参数化查询,不要直接拼接字符串 self.env.cr.execute( """ UPDATE res_partner SET location_latitude = %s, location_longitude = %s WHERE building_id = %s """, (record.latitude, record.longitude, record.id) ) - 视图侧调整
表单视图里的customer_count字段的force_save="1"属性可以去掉,字段本身已经落库,不需要强制保存即可参与筛选。
效果验证
- 新建楼宇绑定客户后,
customer_count会自动更新为实际关联的客户数量,不会停留在0值 - 历史存量楼宇数据在模块升级时,会自动触发一次compute重算,把数据库里存储的0值修正为正确的统计结果
customer_count会正常出现在列表视图的自定义筛选可选字段列表中,支持按数值范围做过滤
内容的提问来源于stack exchange,提问作者Shahal
相关产品推荐
相关产品推荐

