【odoo14】【好书学习】第二十章、odoo的远程过程调用
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调用。
本章内容如下:
- 通过XML-RPC实现登录odoo
2. 通过XML-RPC获取和读取数据(未完成)
3. 通过XML-RPC创建、更新、删除数据(未完成)
4. 通过XML-RPC调用函数(未完成) - 通过JSON-RPC登录odoo
6. 通过JSON-RPC过滤及搜索数据
7. 通过JSON-RPC创建、更新、删除数据
8. 通过JSON-RPC调用函数 - OCA的odoorpc库(超好用)
- 生成API key
技术需求
本章,我们将使用第十九章的my_library模块。可见GitHub repository: https://github.com/ PacktPublishing/Odoo-12-Development-Cookbook-Third-Edition/tree/master/Chapter19/r0_initial_module.
假设你已经有一个在运行的odoo实例,http://localhost:8069,使用名为book-db-14的数据库,安装了名为my_library的模块。
通过XML-RPC实现登录odoo
本节,我们通过RPC实现用户验证并检查用户凭证是否有效。
准备
步骤
- 添加odoo_authenticate.py文件,放在哪里随意。
- 添加代码
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自带的标准包,不用额外安装。
odoo提供/xmlrpc/2/common节点用于XML-RPC调用。此端点用于不需要身份验证的元方法。authentication()方法本身是一个公共方法,因此可以公开调用它。authentication()方法接受四个参数——数据库名称、用户名、密码和用户代理环境。用户代理环境是一个强制参数,但是如果您不想传递用户代理参数,至少要传递空字典。
当您使用所有有效参数执行authenticate()方法时,它将调用Odoo服务器并执行身份验证。然后,如果给定的登录ID和密码是正确的,它将返回用户ID。如果用户不存在或者密码不正确,则返回False。
在通过RPC访问任何数据之前,您需要使用authenticate()方法。这是因为使用错误的凭据访问数据将产生错误。
小贴士
Odoo的在线实例(*.odoo.com)使用OAuth认证,
因此,本地密码没有在实例上设置。要在这些实例上使用XML-RPC,您需要从实例的Settings | Users | Users菜单手动设置用户的密码。
此外,用于访问数据的方法需要用户ID,而不是用户名,因此需要使用authenticate()方法来获取用户ID。
更多
/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)
输出如下
通过XML-RPC搜索和读取数据
通过XML-RPC创建、更新、删除数据
通过XML-RPC调用函数
通过JSON-RPC登录odoo
odoo提供了JSON-RPC。正如其名,JSON-RPC使用JSOM格式,并通过jsonrpc2.0实现。本节,我们将演示如何使用JSON-RPC实现登录及获取数据。
准备
步骤
- 添加jsonrpc_authenticate.py文件
- 添加如下代码:
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获取及搜索数据
本节,我们将了解如何通过JSON-RPC获取数据。
准备
步骤
- 添加jsonrpc_fetch_data.py文件
- 添加代码
# 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函数的参数如下:
- 数据库的名称
- 用户的ID
- 密码
- 模型名称
- 方法名称
- args,变量数组
- kwargs,字典变量
在我们的例子中,我们调用了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")
通过JSON-RPC创建、更新、删除数据
本节,我们将学习如何通过RPC实现CRUD。
准备
步骤
- 添加jsonrpc_operation.py文件
- 添加代码
# 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调用函数
本节,我们将学习如何通过JSON-RPC调用模型方法。比如,我们将调用图书模型的make_available()方法改变图书的状态。
准备
步骤
- 添加jsonrpc_method.py文件
- 添加代码:
# 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库(超好用)
OCA提供了名为odoorpc的包。可为我们提供便捷的方式与odoo实例交互。安装odoorpc:
pip install OdooRPC
步骤
- 添加odoorpc_library.py文件
- 添加代码
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包,如下:
- https://github.com/akretion/ooor
- https://github.com/OCA/odoorpc
- https://github.com/odoo/openerp-client-lib
- http://pythonhosted.org/OdooRPC
- https://github.com/abhishek-jaiswal/php-openerp-lib
生成API key
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。
本文来自博客园,作者:老韩头的开发日常,转载请注明原文链接:https://www.cnblogs.com/xushuotec/p/14531996.html