odoo支持远程过程调用(RPC),你能够经过其余的应用链接odoo的实例。好比,咱们能够经过使用java编写的android应用链接odoo实例展现过时的订单信息。经过odoo的RPC API,咱们能够操做数据库的CURD。odoo的RPC不只仅局限于数据库的CURD,还支持对象的方法调用。odoo的RPC依然适用于odoo内部的权限管理机制。odoo的RPC适用于任意平台、任意语言调用。
odoo提供了两种类型RPC,XML-RPC和JSON-RPC。本章,咱们将学习如何使用RPC。最后,咱们将使用OCA的odoorpc包实现odoo的RPC调用。
本章内容以下:php
本章,咱们将使用第十九章的my_library模块。可见GitHub repository: https://github.com/ PacktPublishing/Odoo-12-Development-Cookbook-Third-Edition/tree/master/Chapter19/r0_initial_module.java
假设你已经有一个在运行的odoo实例,http://localhost:8069,使用名为book-db-14的数据库,安装了名为my_library的模块。python
本节,咱们经过RPC实现用户验证并检查用户凭证是否有效。android
from xmlrpc import client server_url = "http://localhost:8069" db_name = "book-db-14" username = "admin" password = "admin" common = client.ServerProxy("%s/xmlrpc/2/common" % server_url) user_id = common.authenticate(db_name, username, password, {}) if user_id: print("Success: User id is", user_id) else: print("Failed: wrong credentials")
python3 odoo_authenticate.py
本节,咱们经过python的xmlrpc包实现访问odoo实例。这是python自带的标准包,不用额外安装。git
odoo提供/xmlrpc/2/common节点用于XML-RPC调用。此端点用于不须要身份验证的元方法。authentication()方法自己是一个公共方法,所以能够公开调用它。authentication()方法接受四个参数——数据库名称、用户名、密码和用户代理环境。用户代理环境是一个强制参数,可是若是您不想传递用户代理参数,至少要传递空字典。github
当您使用全部有效参数执行authenticate()方法时,它将调用Odoo服务器并执行身份验证。而后,若是给定的登陆ID和密码是正确的,它将返回用户ID。若是用户不存在或者密码不正确,则返回False。sql
在经过RPC访问任何数据以前,您须要使用authenticate()方法。这是由于使用错误的凭据访问数据将产生错误。数据库
小贴士
Odoo的在线实例(*.odoo.com)使用OAuth认证,
所以,本地密码没有在实例上设置。要在这些实例上使用XML-RPC,您须要从实例的Settings | Users | Users菜单手动设置用户的密码。json
此外,用于访问数据的方法须要用户ID,而不是用户名,所以须要使用authenticate()方法来获取用户ID。api
/xmlrpc/2/common端点提供了另外一个方法:version()。您能够在没有凭据的状况下调用此方法。它将返回Odoo实例的版本信息。version()方法的使用示例以下:
from xmlrpc import client server_url = 'http://localhost:8069' common = client.ServerProxy('%s/xmlrpc/2/common' % server_url) version_info = common.version() print(version_info)
输出以下
odoo提供了JSON-RPC。正如其名,JSON-RPC使用JSOM格式,并经过jsonrpc2.0实现。本节,咱们将演示如何使用JSON-RPC实现登陆及获取数据。
import json import random import requests server_url = "http://localhost:8069" db_name = "book-db-14" username = "admin" password = "admin" json_endpoint = "%s/jsonrpc" % server_url headers = {"Content-Type": "application/json"} def get_json_payload(service, method, *args): return json.dumps( { "jsonrpc": "2.0", "method": "call", "params": {"service": service, "method": method, "args": args}, "id": random.randint(0, 100000000), } ) payload = get_json_payload("common", "login", db_name, username, password) response = requests.post(json_endpoint, data=payload, headers=headers) user_id = response.json()["result"] if user_id: print("Success: User id is", user_id) else: print("Failed: wrong credentials")
python3 jsonrpc_authenticate.py
结果以下:
JSON-RPC使用JSON格式经过/jsonrpc端点与服务器交互数据。在咱们的例子中,咱们使用python的requests包发起post请求,固然,你也能够经过其余的包,好比urllib。
JSON-RPC仅支持JSON-RPC 2.0格式的数据负载。你可在https://www.jsonrpc.org/specification。在咱们的例子中,咱们新建了get_json_payload()方法。该方法负责将数据封装成JSON-RPC 2.0格式的负载。方法接受三个参数,service、method及可变参数。JSON-RPC请求体是以JSON格式的,同时请求头需包含{"Content-Type": "application/json"}。返回结果也是JSON格式的。
与XML-RPC相似,全部公开的方法都位于common服务中。所以,咱们以service=common,method=login准备负载。登陆函数须要额外的参数,包括数据库名称、帐户、密码。当咱们的帐户密码经过验证后,将获得用户的ID。
小贴士
get_json_payload()可实现代码复用。
JSON-RPC一样支持version函数。咱们能够获取odoo实例的版本信息。以下:
import json import random import requests server_url = 'http://localhost:8069' json_endpoint = '%s/jsonrpc' % server_url headers = {"Content-Type": "application/json"} def get_json_payload(service, method, *args): ... payload = get_json_payload('common', 'version') response = requests.post(json_endpoint, data=payload, headers=headers) print(response.json())
结果以下:
本节,咱们将了解如何经过JSON-RPC获取数据。
# place authentication and get_json_payload methods (see first jsonrpc recipe) if user_id: # search for the book's ids search_domain = ['|', ['name', 'ilike', 'odoo'],['name', 'ilike', 'sql']] payload = get_json_payload("object", "execute_kw",db_name, user_id, password, 'library.book', 'search',[search_domain], {'limit': 5}) res = requests.post(json_endpoint, data=payload, headers=headers).json() print('Search Result:', res) # ids will be in result keys # read data for books ids payload = get_json_payload("object", "execute_kw", db_name, user_id, password,'library.book', 'read', [res['result'],['name', 'date_release']]) res = requests.post(json_endpoint, data=payload, headers=headers).json() print('Books data:', res) else: print("Failed: wrong credentials")
python3 jsonrpc_fetch_data.py
结果以下:
在上一节中,咱们经过JSON-RPC登陆系统并得到用户的ID。如今咱们能够经过用户的ID来获取模型数据了。咱们须要使用search及read来获取数据。为了获取数据,咱们调用了object做为service,execute_kw()做为method执行查询。execute_kw函数的参数以下:
在咱们的例子中,咱们调用了search方法。execute_kw()函数将强制变量做为位置变量,将可选变量做为关键字变量。在search方法中,domain是强制变量,可选变量Limit是关键字变量。
步骤2,咱们调用了read方法获取图书的详细信息。并将图书id的列表及字段的列表做为参数。
小贴士
咱们也可使用execute方法。该方法并不支持关键字变量,所以若是你想传递一些可选参数,你须要传递全部的中间参数。
与XML-RPC相似,咱们可使用search_read()方法代替search()及read()方法的组合。以下:
# place authentication and get_json_payload methods (see firstjsonrpc recipe) if user_id: # search and read for the book's ids search_domain = ['|', ['name', 'ilike', 'odoo'],['name', 'ilike', 'sql']] payload = get_json_payload("object", "execute_kw", db_name, user_id, password, 'library.book', 'search_read', [search_domain, ['name', 'date_release']], {'limit': 5}) res = requests.post(json_endpoint, data=payload, headers=headers).json() print('Books data:', res) else: print("Failed: wrong credentials")
本节,咱们将学习如何经过RPC实现CRUD。
# place authentication and get_json_payload method (seelast recipe for more) if user_id: # creates the books records create_data = [ {'name': 'Book 1', 'date_release': '2019-01-26'}, {'name': 'Book 3', 'date_release': '2019-02-12'}, {'name': 'Book 5', 'date_release': '2019-05-08'}, {'name': 'Book 7', 'date_release': '2019-05-14'} ] payload = get_json_payload("object", "execute_kw",db_name, user_id, password, 'library.book','create', [create_data]) res = requests.post(json_endpoint, data=payload,headers=headers).json() print("Books created:", res) books_ids = res['result'] # Write in existing book record book_to_write = books_ids[1] # We will use ids of recently created books write_data = {'name': 'Book 2'} payload = get_json_payload("object", "execute_kw",db_name, user_id, password, 'library.book','write', [book_to_write, write_data]) res = requests.post(json_endpoint, data=payload,headers=headers).json() print("Books written:", res) # Delete in existing book record book_to_unlink = books_ids[2:] # We will use ids of recently created books payload = get_json_payload("object", "execute_kw", db_name, user_id, password, 'library.book', 'unlink', [book_to_unlink]) res = requests.post(json_endpoint, data=payload,headers=headers).json() print("Books deleted:", res) else: print("Failed: wrong credentials")
python3 jsonrpc_operation.py
结果以下:
若是操做成功,write和unlink方法返回True。这意味着,若是您的响应为True,则假定一条记录已被成功更新或删除。
execute_kw()函数用于create、update和delete运算。自odoo12,create方法支持同时建立多条数据。
小贴士
当您尝试建立记录而没有为required字段提供值时,JSON-RPC和XML-RPC都会生成一个错误,所以请确保您已经将全部required字段添加到建立值中。
与XML-RPC同样,您可使用JSON-RPC中的check_access_rights方法来检查您是否有执行该操做的访问权限。这个方法须要两个参数——模型名称和操做名称。在下面的示例中,咱们检查create操做的访问权限:
# place authentication and get_json_payload method (see lastrecipe for more) if user_id: payload = get_json_payload("object", "execute_kw", db_name, user_id, password,'library.book', 'check_access_rights', ['create']) res = requests.post(json_endpoint, data=payload, headers=headers).json() print("Has create access:", res['result']) else: print("Failed: wrong credentials")
结果以下:
本节,咱们将学习如何经过JSON-RPC调用模型方法。好比,咱们将调用图书模型的make_available()方法改变图书的状态。
# place authentication and get_json_payload method (see last recipe for more) if user_id: # Create the book in draft state payload = get_json_payload("object", "execute_kw",db_name, user_id, password,'library.book', 'create', [{'name': 'Book 1','state': 'draft'}]) res = requests.post(json_endpoint, data=payload,headers=headers).json() print("Has create access:", res['result']) book_id = res['result'] # Change the book state by calling make_available # method payload = get_json_payload("object", "execute_kw",db_name, user_id, password,'library.book', 'make_available', [book_id]) res = requests.post(json_endpoint, data=payload,headers=headers).json() # Check the book status after method call payload = get_json_payload("object", "execute_kw",db_name, user_id, password, 'library.book', 'read', [book_id,['name', 'state']]) res = requests.post(json_endpoint, data=payload,headers=headers).json() print("Book state after the method call:",res['result']) else: print("Failed: wrong credentials")
python3 jsonrpc_method.py
前面的命令将使用draft建立一本书,而后经过调用make_available方法更改该书的状态。以后,咱们将获取图书数据来检查图书的状态,这将产生如下输出:
execute_kw()可以调用模型的任何公共方法。正如咱们在经过XML-RPC配方调用方法中看到的,公共方法是那些名称不以_(下划线)开头的方法。以_开头的方法是私有的,你不能从JSON-RPC调用它们。
在咱们的示例中,咱们建立了一个状态为draft的书籍。而后,咱们再进行一次RPC调用来调用make_available方法,这将把该书的状态更改成available。最后,咱们再进行一次RPC调用来检查book的状态。这将显示该书的状态已更改成available,如图20.10所示。
不返回任何内容的方法在内部默认返回None。这些方法不能从RPC中使用。所以,若是您想使用来自RPC的方法,至少要添加return True语句。
OCA提供了名为odoorpc的包。可为咱们提供便捷的方式与odoo实例交互。安装odoorpc:
pip install OdooRPC
import odoorpc db_name = 'book-db-14' user_name = 'admin' password = 'admin' # Prepare the connection to the server odoo = odoorpc.ODOO('localhost', port=8069) odoo.login(db_name, user_name, password) # login # User information user = odoo.env.user print(user.name) print(user.company_id.name) print(user.email) BookModel = odoo.env['library.book'] search_domain = ['|', ['name', 'ilike', 'odoo'], ['name', 'ilike', 'sql']] books_ids = BookModel.search(search_domain, limit=5) for book in BookModel.browser(books_ids): print(book.name, book.date_release) # create the book and update the state book_id = BookModel.create({'name': 'Test book', 'state': 'draft'}) print("Book state before make_available:", book.state) book = BookModel.browse(book_id) book.make_available() book = BookModel.browse(book_id) print("Book state before make_available:", book.state)
python3 odoorpc_library.py
结果以下:
odoorpc在底层使用的jsonrpc实现与odoo的交互。
odoorpc为咱们作了很是完美的封装,但咱们依然能够会用原生的RPC语法:
import odoorpc db_name = 'book-db-14' user_name = 'admin' password = 'admin' # Prepare the connection to the server odoo = odoorpc.ODOO('localhost', port=8069) odoo.login(db_name, user_name, password) # login books_info = odoo.execute('library.book', 'search_read', [['name', 'ilike', 'odoo']], ['name', 'date_release']) print(books_info)
还有几个其余的odoo rpc包,以下:
odoo14开始支持双因素认证(Two-Factor Authentication, 2FA)。2FA是用户账户的额外安全层,用户须要输入密码和基于时间的代码。若是您已经启用了2FA,那么您将不能经过输入用户ID和密码来使用RPC。要解决这个问题,您须要为用户生成一个API密钥。本节,咱们将看到如何生成API密钥。
打开用户首选项并打开账户安全选项卡。
点击New API Key按钮:
它将打开一个弹出窗口,以下图所示。输入API密钥名和点击Generate key按钮:
这将生成API密钥,并在一个新的弹出窗口中显示它。记下API键,由于你还须要它:
一旦生成了API密钥,您就能够开始以与普通密码相同的方式为RPC使用API密钥。
使用API键很简单。然而,有一些事情你须要注意。API密钥是为每一个用户生成的,若是您但愿为多个用户使用RPC,则须要为每一个用户生成API密钥。此外,用户的API密钥将拥有与用户相同的访问权限,所以若是某人得到了密钥的访问权限,他们能够执行用户能够执行的全部操做。所以,您须要对API密钥保密。
小贴士
生成API密钥时,只显示一次。你得把这个键记下来。若是你失去了它,就没有办法再找回来了。在这种状况下,您须要删除API键并生成一个新的API键。
使用API密钥很是简单。在RPC调用期间,您只须要使用API密钥而不是用户密码。即便激活了2FA,你也能够调用RPC。