Odoo 的 jsonrpc 接口及参数解释

Odoo 的 WEB 前端是完全通过接口和后端通讯的,几乎实现了前后端分离。主要通过 JSONRPC。登录成功后就可以向 Odoo 后台发送 JSONRPC了。

以下几个接口是经常使用的:

1)model 搜索

接口地址:web/dataset/search_read
接口参数:JSRONRPC 参数,下面描述
接口作用:所有列表视图或者 kanban 视图都需要调用的接口,支持参数 offset 和 limit,还有 sort,就是可以用来分页获取数据表的中的记录。如 offset 10, limit 20,就是从第10条记录开始获取 20 条。当然它也返回总的满足搜索条件的记录数量,这样调用者才知道要分多少个页才能把数据都捞出来。

如果用这些接口来开发原生的 Android 应用,

    @Headers({"Content-Type: application/json","Accept: application/json"})
    @POST("web/dataset/search_read")
    Call postSearchRead(@Body RequestBody body);

上文代码是使用 Android 中 Retrofit 对 HTTP 接口的一个描述。

参数一般形如:

{
  jsonrpc: "2.0",
  method: "call",
  id:  651978786,
  params:  {
      model: ""
      domain: [[]]
      fields: ["id", "name", …]
      limit: 80
      sort: ""
      context: {
          lang: "zh_CN",
          tz: false,
          uid: 2,
          allowed_company_ids: [1]
         }
    }
}

jsonrpc, method, id 这三个字段是必须提供的,其中 id 的值一直在变大,用秒表示就可以,因为这个id 表示这个请求的唯一性,没有任何其它含义,Odoo 后台若有任何结果返回都会有这个相同的 id,表示这个返回结果对应的哪个请求。

params 中主要包含 model,是表名称,domain 是搜索条件,fields 是要返回的数据字段名称列表,如果没有指定就返回所有字段,limit 是限制返回记录条数,offset 没有就是0,context 也是一个通用结构,这里面往往含有用户的 session 数据。

请求的结果:

{"jsonrpc": "2.0", "id": 651978786, "result": {"length": 85, "records": [{}, {}]}}

length 是所有满足搜索条件的记录数量,不是这次返回了多少个,返回多少个需要通过看 records 数组的长度,records 数组里面的每一项就是一个记录。

2)数据记录的 读、写、创建

接口名称:call kw (以 KEY WORD 方式调用)
接口地址:web/dataset/call_kw/{model}/{method}
接口参数:下面描述
接口作用:call kw 这个接口有一定的泛化性,可以支持很多操作,CRUD 都需要使用这个接口,自己写一个 model 中的 method 接口也是需要使用这个接口。其中 model 和 method 是补全这个调用 URL 必须提供的,如读一个表叫做 test_table 的记录就需要调用 web/dataset/call_kw/test_table/read。具体的记录 id 要在参数中提供。

基本的参数的结构:

{
  jsonrpc: "2.0",
  method: "call",
  id:  651978786,
  params:  {
    args: [[id], ["id", "name"]],
    kwargs:{
      context: {}
    },
    method: "read",
    model:"test_table"
  }
}

params 中 method 和 model 和 url 中的一样,分别是要调用的方法名和表名称。 args 是个数组,第一个元素是记录 id,第二个是字段名称列表。

kwargs 只有一个参数,即上文提到的 context ,含有用户 session 的一些内容。

返回结果:

{"jsonrpc": "2.0", "id": 268487428, "result": [{"id": 1305,  "name":""}]

如果某个field 没有值,就是 false。

同样 method 可以是 read/create/write 基本差不多,read 和 write 要提供 id,而create 没有 id。

3)upload attachment

接口名称:upload attachment
接口地址:web/binary/upload_attachment
接口参数:表单 (不再是 JSON)
接口作用:可以上传 附件文件,返回文件 id,这个 id 可以用在数据表之中

    @POST("web/binary/upload_attachment")
    Call postUploadAttachment(@Body MultipartBody body);

上面是 Retrofit 的接口描述,body 需要再构造:

      // upload then return the attachment id, ticket db table store the id
        MultipartBody.Builder b = new MultipartBody.Builder();
        MultipartBody body = b.setType(MultipartBody.FORM)
                .addFormDataPart("csrf_token", "csrf_token...")
                .addFormDataPart("callback", "any-upload-id")
                .addFormDataPart("model", "model")
                .addFormDataPart("id", "0")
                .addFormDataPart("ufile", localFileName(),
                        RequestBody.create(MediaType.parse("image/jpeg"), localFile))
                .build();

上述代码能够在 Android Java 中构造一个上传文件的请求。可以看出来是要求提供一个 multipart form 的表单,必须提供 csrf token;callback 是个字符串,实际上是一个页面元素的 id,在系统返回值中使用了这个 id ; model 就是表名称,说明这个附件是为哪个表准备的;id 一般来说应给是记录 id,但是没用上,传 0 即可,因为附件属于哪个表的哪个记录由记录本身维护一个列表决定;ufile 必须是这个名字,来代表文件。所有参数名称必须严格一致,因为后台是需要跟 Python 函数参数映射的,名字对不上必然出错。

上传成功后会返回一段 Javascript 代码,这段代码。


通过查看 Odoo 的页面构造代码: