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。