Odoo创建ir.cron时报psycopg2.errors.NotNullViolation错误如何解决
报错根因
你遇到的非空约束报错直接原因是Odoo创建定时任务关联的服务动作(ir.actions.server)时,缺少必填的model_id字段值:
- Odoo的
ir.cron定时任务在state=code模式下,底层会自动生成一条关联的ir.actions.server记录,该表的model_id字段为非空必填项 - 你编写的XML中只使用了
model字段赋值,该字段是旧版本Odoo的废弃写法,无法正确给关联的服务动作传递模型ID值,因此插入数据库时触发非空约束报错。
除此之外,你的业务逻辑也存在设计问题:
- 你定义的
group_change方法要求传入vals参数,但定时任务调用时没有传参入口,执行时会触发参数不匹配报错 - 用每分钟轮询的方式监听用户组变更效率极低,且无法实时捕获变更,存在漏日志的可能。
修复方案
方案1:保留定时任务逻辑的修复
如果一定要用定时任务实现,按如下修改:
- 修改XML定时任务定义,替换
model字段为model_id,并把方法调用逻辑写在code字段中:
<?xml version="1.0" encoding="UTF-8"?> <odoo> <data noupdate="1"> <record id="log_res_groups" model="ir.cron"> <field name="name">Log User Changes</field> <field name="active" eval="True"/> <field name="user_id" ref="base.user_root"/> <field name="interval_number">1</field> <field name="interval_type">minutes</field> <field name="numbercall">-1</field> <field name="doall">1</field> <field name="state">code</field> <field name="model_id" ref="base.model_res_users"/> <field name="code">model.search([]).group_change()</field> </record> </data> </odoo>
- 调整
group_change方法逻辑,去掉不必要的vals参数和super调用,自行实现两次轮询的用户组差异对比逻辑即可。
方案2:更合理的事件触发方案(推荐)
直接重写res.users的write方法,用户组变更时实时触发日志记录,不需要定时任务,性能更高更准确:
from odoo import models import logging _logger = logging.getLogger(__name__) class Users(models.Model): _inherit = 'res.users' def write(self, vals): if 'groups_id' not in vals: return super().write(vals) # 变更前统计用户组数量 pre_group_count = len(self.groups_id) res = super().write(vals) # 变更后统计用户组数量 post_group_count = len(self.groups_id) if pre_group_count > post_group_count: _logger.info("Admin user %s, removed %s from group", self.env.user.name, self.name) elif pre_group_count < post_group_count: _logger.info("Admin user %s, added %s to a group", self.env.user.name, self.name) return res
修改完成后直接删除原来的定时任务XML即可。
内容的提问来源于stack exchange,提问作者Justin Young
相关产品推荐
相关产品推荐

