Odoo JsonRPC的参数传递分析 - xiaohao0576/odoo-doc GitHub Wiki
网址入口
https://database_name.odoo.com/jsonrpc
--header 'Content-Type: application/json'
JSON数据格式
{"jsonrpc": "2.0", "method": "call", "params": {"arg1": "val1" }, "id": 123232}
"jsonrpc": "2.0"
这个是固定的,不变化
"method": "call"
,这个也是固定的, method的值odoo会忽略
params
,这个key是必须的,很重要,下面会讲具体的格式
id
,这个使用随机数字就可以
参考代码: https://github.com/odoo/odoo/blob/62d05a7a942ca344ca8ad02bc27ec58a565cab75/odoo/http.py#L2295
params的格式
@route('/jsonrpc', type='json', auth="none", save_session=False)
def jsonrpc(self, service, method, args):
""" Method used by client APIs to contact OpenERP. """
_check_request()
return dispatch_rpc(service, method, args)
根据上面的代码, service
, method
, args
这三个参数是必需要有的,也就是从params数组中提取出来的
其中,service有以下三个取值, common
,db
,object
, 分别对应三个不同的dispatch
rpc_dispatchers = {
'common': odoo.service.common.dispatch,
'db': odoo.service.db.dispatch,
'object': odoo.service.model.dispatch,
}
service取值object
当service取值object的时候, method固定为execute_kw
, 代码如下
def execute_kw(db, uid, obj, method, args, kw=None):
return execute(db, uid, obj, method, *args, **kw or {})
- 当service取值object的时候, args是一个数组,传递后的参数名称又变成了parms, 前三个位置参数一定是 db, uid, passwd
- 第四个参数是 obj的名字,比如
res.partner
- 第五个参数是obj里面的公开方法,比如
read
- 第6个参数是一个数组,传递给上面的方法的位置参数,不能省略,就算没有参数,也需要写一个空的列表, []
- 第7个参数可选,是一个字典,表示命名参数, 可以传递context,这个context也能在服务器动作中获取
def dispatch(method, params):
db, uid, passwd = params[0], int(params[1]), params[2]
security.check(db, uid, passwd)
threading.current_thread().dbname = db
threading.current_thread().uid = uid
registry = Registry(db).check_signaling()
with registry.manage_changes():
if method == 'execute':
res = execute(db, uid, *params[3:])
elif method == 'execute_kw':
res = execute_kw(db, uid, *params[3:])
else:
raise NameError("Method not available %s" % method)
return res
参考链接: https://github.com/odoo/odoo/blob/62d05a7a942ca344ca8ad02bc27ec58a565cab75/odoo/service/model.py#L47
最终调用 call_kw函数
def call_kw(model, name, args, kwargs):
""" Invoke the given method ``name`` on the recordset ``model``. """
method = getattr(model, name, None)
if not method:
raise AttributeError(f"The method '{name}' does not exist on the model '{model._name}'")
api = getattr(method, '_api', None)
if api:
# @api.model, @api.model_create -> no ids
recs = model
else: # 如果方法没有用@api.model , @api.model_create装饰, 就把args第一个参数作为record的ids, 比如下面例子中调用服务器动作的run方法
ids, args = args[0], args[1:]
recs = model.browse(ids)
# altering kwargs is a cause of errors, for instance when retrying a request
# after a serialization error: the retry is done without context!
# kwargs里面的context对象,会被单独取出来,作为records的context字典
kwargs = dict(kwargs)
context = kwargs.pop('context', None) or {}
recs = recs.with_context(context)
_logger.debug("call %s.%s(%s)", recs, method.__name__, Params(args, kwargs))
result = getattr(recs, name)(*args, **kwargs)
if api == "model_create":
# special case for method 'create'
result = result.id if isinstance(args[0], Mapping) else result.ids
else:
result = downgrade(method, result, recs, args, kwargs)
return result
源码链接: https://github.com/odoo/odoo/blob/7fc2cf32e5f6d1699ed17ef832eec4e9b2679358/odoo/api.py#L514
返回值
如果没有错误,返回值如下
response = {'jsonrpc': '2.0', 'id': self.request_id, 'result':{}}
如果有错误,返回值如下
response = {'jsonrpc': '2.0', 'id': self.request_id, 'error':{}}
参考代码
def _response(self, result=None, error=None):
response = {'jsonrpc': '2.0', 'id': self.request_id}
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
return self.request.make_json_response(response)
示例payload
curl --location 'https://database_name.odoo.com/jsonrpc' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "call",
"params": {
"service": "object",
"method": "execute_kw",
"args": [
"database_name",
6,
"79a46api_key787dsfs",
"ir.actions.server",
"run",
[1105](/xiaohao0576/odoo-doc/wiki/1105),
{"context": {"lang": "zh_CN","chat_id": "777766666"}}
],
"kwargs": {}
},
"id": 12121
}'