Odoo 17调用action.post时报错,发票状态已变更仍异常
Odoo 17 XML-RPC调用action_post报错:cannot marshal None unless allow_none is enabled
问题原因
Odoo 17中account.move的action_post方法返回值变更为None,而Odoo默认的XML-RPC服务端在序列化响应时设置allow_none=False,无法处理None值,因此抛出序列化错误。你之前尝试开启allow_none是在客户端设置,但问题出在服务端的响应序列化环节,所以客户端设置无效。
注意:虽然报错,但发票实际已完成过账(状态变更、凭证号生成),因为action_post的核心逻辑已经执行完成,只是返回值序列化失败。
解决办法
方法1:通过自定义模块修改服务端XML-RPC配置
创建自定义模块,继承base模块的RPC控制器,修改响应序列化时的allow_none参数为True:
- 在自定义模块下创建
controllers/rpc.py:
from odoo import http from odoo.addons.base.controllers.rpc import RPC import xmlrpc.client class RPCAllowNone(RPC): @http.route() def xmlrpc_2(self, service): return self._xmlrpc(service) def _xmlrpc(self, service): result = super()._xmlrpc(service) # 修改allow_none为True,支持None值序列化 return http.Response( xmlrpc.client.dumps((result,), methodresponse=1, allow_none=True), content_type='text/xml; charset=utf-8', )
- 安装该自定义模块后,原XML-RPC调用即可正常执行,无需修改客户端代码。
方法2:封装安全调用方法(推荐)
在Odoo中扩展account.move模型,添加一个返回非None值的封装方法,避免直接调用返回None的action_post:
- 在自定义模块下创建
models/account_move.py:
from odoo import models class AccountMove(models.Model): _inherit = 'account.move' def action_post_safe(self): # 执行原过账逻辑 self.action_post() # 返回发票ID作为响应,确保非None可序列化 return self.id
- 客户端调用时替换为该自定义方法:
models.execute_kw(odoo_db_name, uid, odoo_key, 'account.move', 'action_post_safe', [new_invoice_id])
这种方式符合Odoo扩展规范,无需修改核心代码,同时彻底解决序列化问题。
方法3:客户端捕获异常(临时方案)
如果仅需临时绕过,可在客户端捕获该特定异常并忽略(因为发票已成功过账):
import xmlrpc.client try: models.execute_kw(odoo_db_name, uid, odoo_key, 'account.move', 'action_post', [new_invoice_id]) except xmlrpc.client.Fault as e: if "cannot marshal None unless allow_none is enabled" in str(e): # 忽略序列化异常,发票已过账完成 pass else: # 其他异常正常抛出 raise
内容的提问来源于stack exchange,提问作者B0K1NG
相关产品推荐
相关产品推荐

