Odoo 服務器端帶有外部 API,可供網頁客戶端和其它客戶端應用使用。本文中咱們將學習如何在咱們的客戶端程序中使用 Odoo 的外部 API。爲避免引入你們所不熟悉的編程語言,此處咱們將使用基於 Python 的客戶端,但這種 RPC 調用的處理方法也適用於其它編程語言。html
咱們將一塊兒瞭解如何使用 Odoo RPC調用,而後根據所學知識使用 Python建立一個簡單的圖書命令行應用。python
本文主要內容有:git
本文基於第三章 Odoo 12 開發之建立第一個 Odoo 應用建立的代碼,具體代碼請參見 GitHub 倉庫。應將library_app模塊放在addons路徑下並進行安裝。爲保持先後一致,咱們將使用第二章 Odoo 12開發之開發環境準備所進行安裝並使用12-library數據庫。本章完成後的代碼請參見 GitHub 倉庫。github
補充:因原書先後曾使用過多個數據庫,本文中Alan將使用系列中一直使用的 dev12數據庫,並在前一篇文章的基礎上進行開發。web
本文中,咱們將開發一個簡單的客戶端應用來管理圖書目錄。這是一個命令行接口(CLI) 應用,使用 Odoo 來做爲後端。應用的功能很是有限,這樣咱們能夠聚焦在用於與 Odoo服務端交互的技術,而不是具體應用的實現細節。咱們的簡單應用能夠完成以下功能:shell
這個應用是一個 Python 腳本,等待輸入命令來執行操做。使用會話示例以下:數據庫
Odoo API 能夠在外部經過兩種協議訪問:XML-RPC和JSON-RPC。任意外部程序,只要能實施其中一種協議的客戶端,就能夠與 Odoo 服務端進行交互。爲避免引入其它編程語言,咱們將保持使用 Python 來研究外部 API。編程
到目前爲止咱們僅在服務端運行了 Python 代碼。如今咱們要在客戶端上使用 Python,因此你可能須要在電腦上作一些額外設置。要學習本文的示例,你須要能在操做電腦上運行 Python 文件。可經過在命令行終端運行python3 –version命令來進行確認。若是沒有安裝,請參考官方網站針對你所使用的平臺的安裝包。後端
對於 Ubuntu,你可能已經安裝了 Python 3,若是沒有安裝,可經過如下命令進行安裝:sublime-text
若是你使用的是 Windows 而且已安裝了 Odoo,可能會奇怪爲何沒有 Python 解釋器,還須要進行額外安裝。簡單地說是由於 Odoo 安裝帶有一個內嵌的 Python 解釋器,沒法在外部使用。
訪問服務的最簡單方法是使用XML-RPC,咱們可使用 Python 標準庫中的xmlrpclib來實現。不要忘記咱們是在編寫客戶端程序鏈接服務端,所以需運行 Odoo 服務端實例來供鏈接。本例中咱們假設 Odoo 服務端實例在同一臺機器上運行,但你可使用任意運行服務的其它機器,只要能鏈接其IP 地址或服務器名。
讓咱們來初次鏈接 Odoo 外部 API。打開 Python 3終端並輸入以下代碼:
這裏咱們導入了xmlrpc.client庫,而後建立了一個包含服務地址和監聽端口信息的變量。請根據自身情況進行修改(如 Alan 使用srv = ‘http://192.168.16.161:8069’)。
下一步訪問服務端公共服務(無需登陸),在終端地址/xmlrpc/2/common上暴露。其中一個可用方法是version(),用於查看服務端版本。咱們使用它來確承認與服務端進行通信。
另外一個公共方法是authenticate()。你可能你會覺得它會建立會話,但實際上不會。該方法僅僅確認用戶名和密碼可被接受,請求不使用用戶名而是它返回的用戶 ID。示例以下:
首先建立變量 db,來存儲使用的數據庫名。本例中爲 dev12,但能夠修改成任意其它你所使用的數據庫名。若是登陸信息錯誤,將不會返回用戶 ID,而是返回 False 值。authenticate()最後一個參數是用戶代理(User Agent)環境,用於提供客戶端的一些元數據(metadata),它是必填的,但能夠是一個空字典。
使用XML-RPC,不會維護任何會話,每次請求都會發送驗證信息。這讓協議太重,但使用簡單。下一步咱們設置訪問需登陸才能訪問的服務端方法。暴露的終端地址爲/xmlrpc/2/object,示例以下:
此處咱們第一次訪問了服務端 API,執行了Partner 記錄的計數。經過 execute_kw() 方法來調用方法,接收以下參數:
上面的例子中對res.partner模型調用了search_count方法,僅一個位置參數[],沒有關鍵字參數。該位置參數是一個搜索域,因咱們傳入的是一個空列表,它對全部夥伴進行計數。經常使用的操做有搜索和讀取。在使用RPC調用時,search方法返回一個區塊的 ID 列表。browse方法不可用於RPC,而應使用read來獲得記錄 ID 列表並獲取相應數據,示例以下:
對於 read 方法,咱們使用了一個位置參數[14]來做爲 ID 列表,以及一個關鍵字參數fields。還能夠看到many-to-one關聯字段如country_id,被成對獲取,包含關聯的記錄 ID 和顯示名稱。在代碼中處理數據時應記住這一點。
常常會使用search和 read 的組合,因此提供了一個search_read方法來在同一步中執行二者的操做。可經過以下命令來獲取以上兩段代碼的一樣結果:
補充:以上代碼會爲 read 方法傳入全部 search 方法的結果,所以內容要較僅傳入[14]多
search_read方法和 read 類似,但須要 domain代替 id 列表來做爲第一個位置參數。須要說明在 read 和search_read中fields參數並不是必須。若是不傳入,則獲取全部字段。這可能會帶來對函數字段的大量計算,而且獲取大量可能歷來都不會用到的數據,因此一般建議明確傳入字段列表。
在第七章 Odoo 12開發之記錄集 – 使用模型數據咱們學習了用於生成記錄的最重要的模型方法以及代碼書寫。但還有一些其它模型方法可用於更具體的操做,如:
全部其它模型方法都對 RPC 暴露,但如下劃線開頭的除外,這些是私有方法。也就是說咱們能夠像下面這樣使用create, write,和unlink修改服務端數據:
XML-RPC的一個缺陷是它不支持 None 值。有一個XML-RPC擴展能夠支持 None 值,但這取決於咱們客戶端所依賴的具體XML-RPC庫。不返回任何值的方法不能在XML-RPC中使用,由於默認返回的是 None。這也是爲何方法在結束時至少會帶有一個return True語句。另外一個方案是使用 Odoo 同時支持的JSON-RPC。OdooRPC對其進行運行,在稍後的使用OdooRPC庫一節會進行使用。
應反覆強調 Odoo 的外部 API 可在大部分編程語言中使用。官方文檔中咱們能夠看到Ruby, PHP和Java實際示例。
ℹ️如下劃線開頭的模塊方法被認爲是私有方法,不對XML-RPC暴露。
下面就來實現圖書客戶端應用。咱們將使用兩個文件:一個處理服務端的接口:library_api.py,另外一個處理應用的用戶界面:library.py。而後咱們會使用現有的OdooRPC庫來提供一個替代的實現方法。
咱們將建立類來配置與 Odoo 服務端的鏈接,以及讀取/寫入圖書數據。這將暴露基本的增刪改查方法:
選擇一個目錄來放置應用文件並建立library_api.py文件。首先添加類的構造方法,代碼以下:
此處咱們存儲了全部建立執行模型調用的對象的全部信息:API引用、uid、密碼、數據庫名和要使用的模型。接下來咱們定義一個幫助方法來執行調用。有賴於前面對象存儲的數據該方法能夠很精煉:
如今就可使用它來實現更高級的方法了。search_read()方法接收一個可選的 ID 列表來獲取數據。若是沒傳入數據,則返回全部記錄:
create()方法用於建立給定書名的新書並返回所建立記錄的 ID:
write()方法中傳入新書名和圖書 ID 做爲參數,並對該書執行寫操做:
而後咱們能夠實現unlink()方法,很是簡單:
在該Python文件最後添加一段測試代碼在運行時執行:
若是執行以上 Python 腳本,咱們能夠打印出圖書的內容:
如今已經有了對 Odoo 後端的簡單封裝,下面就能夠處理命令行用戶界面了。
個人目標是學習如何寫外部應用和 Odoo 服務之間的接口,前面已經實現了。但不能止步於此,咱們還應讓終端用戶可使用它。爲使設置儘可能簡單,咱們將使用 Python 內置功能來實現這個命令行應用。該功能是標準庫自帶的,所以不須要進行額外的安裝。
在library_api.py 同目錄,新建一個library.py文件。首先導入命令行參數解析器,而後導入LibraryAPI類,代碼以下:
下面咱們來看看參數解析器接收的命令,有如下四個命令:
在命令行解析器中添加這些命令的代碼以下:
這裏 args 是一個包含傳入腳本參數的對象,args.command是提供的命令,args.params是可選項,用於存放命令所需的其它參數。若是使用了不存在或錯誤的命令,參數解析器會進行處理並提示用戶應輸入的內容。有關argparse更完整的說明,請參考官方文檔。
下一步是執行所計劃的操做。首先爲 Odoo服務準備鏈接:
第一行代碼設置服務實例的一些固定參數以及要鏈接的數據庫。本例中,咱們鏈接 Odoo 服務本機(localhost),監聽8069默認端口,並使用 dev12數據庫。如需鏈接其它服務器和數據庫,請對參數進行相應調整。
這裏硬編碼了服務器地址而且密碼使用了明文,顯然與最佳實施相差甚遠。咱們應該包含配置步驟讓客戶提供相關設置信息,並以安全的方式進行存儲。但此處咱們的目標是學習使用 Odoo RPC,因此可把它看做概念代碼,而非已完成的產品。下面寫代碼來利用 api 對象處理所支持的命令。咱們能夠先寫list命令來列出圖書:
這裏咱們使用了LibraryAPI.search_read()來從服務端獲取圖書記錄列表。而後遍歷列表中每一個元素並打印。咱們使用 Python 字符串格式化來向用戶顯示每條圖書記錄,記錄是一個鍵值對字典。下面添加add命令,這裏使用了額外的書名做爲參數:
由於主要的工做已經在LibraryAPI對象中完成,下面咱們只要調用write()方法並向終端用戶顯示結果便可。 set-title命令容許咱們修改已有圖書的書名,應傳入兩個參數,新的書名和圖書的 ID:
最終咱們要實現 del 命令來刪除圖書記錄,學到這裏應該再也不有任何挑戰性了:
到這裏咱們就完成了基礎的 API CLI (命令行接口)了,讀者能夠嘗試執行命令來查看效果。好比,咱們能夠運行本文開頭學習項目-圖書目錄客戶端中的命令。經過普通客戶端來訪問圖書中的數據也會有助於確認該CLI是否如預想般運行。這是一個很是基礎的應用,查看代碼你應該能夠想到一些改進它的方式。但要記住咱們這裏的目的是以相對有趣的方式舉例說明Odoo RPC API的使用。
另外一個能夠考慮的客戶端庫是OdooRPC。它是一個更流行的客戶端庫,使用JSON-RPC 協議而不是XML-RPC。事實上 Odoo 官方客戶端使用的就是JSON-RPC,XML-RPC更可能是用於支持向後兼容性。
ℹ️OdooRPC庫如今由 OCA 管理和持續維護。瞭解更多請參見OCA。
OdooRPC庫可經過PyPI安裝:
不論是使用JSON-RPC仍是XML-RPC,Odoo API的使用方式並沒什麼分別。因此在下面咱們能夠看一些細節可能有區別,但這些客戶端庫的使用方式並無什麼分別。
OdooRPC庫在建立新的odoorpc.ODOO對象時創建服務端鏈接,而後應使用ODOO.login()方法來建立用戶會話。和服務端類似,會話有一個帶有會話環境的 env 屬性,包含用戶 ID-uid 和上下文。咱們可使用OdooRPC來從新實現library_api.py對服務端的接口。它應提供相同的功能,但使用JSON-RPC代替XML-RPC來實施。在相同目錄下建立library_odoorpc.py文件並加入以下代碼:
OdooRPC庫實現Model和Recordset對象來模仿服務端對應的功能。目標是在客戶端編程與服務端編程應基本一致。客戶端使用的方法將經過存儲在self.Model屬性中的圖書模型來利用這點。這裏實現的execute()方法並不會在咱們客戶端中使用,僅用於與本文中討論的其它實現進行對比。
下面咱們來實現search_read(), create(), write()和unlink()這些客戶端方法。在相同文件的LibraryAPI()類中添加以下方法:
注意這段代碼和 Odoo 服務端代碼類似,由於它使用了與 Odoo 中插件寫法相近的 API。而後能夠將library.py文件中的from library_api import LibraryAPI一行修改成library_odoorpc import LibraryAPI。如今再次運行library.py客戶端應用進行測試,執行的效果和以前應該一致。
ERPpeek是一個多功能工具,既能夠做爲交互式命令行接口(CLI)也能夠做爲 Python庫,它提供了比xmlrpc庫更便捷的 API。它在PyPi索引中,可經過以下命令安裝:
ERPpeek不只可用做 Python 庫,它還可做爲 CLI 來在服務器上執行管理操做。Odoo shell 命令在主機上提供了一個本地交互式會話功能,而erppeek庫則爲網絡上的客戶端提供了一個遠程交互式會話。打開命令行,經過如下命令可查看可以使用的選項:
下面一塊兒來看看一個示例會話:
如上所見,創建了服務端的鏈接,執行上下文引用了model() 方法來得到模型實例並對其進行操做。鏈接使用的erppeek.Client實例也可經過客戶端變量來使用。 值得一提的是它可替代網頁客戶端來管理所安裝的插件模塊:
所以ERPpeek可做爲 Odoo 服務端遠程管理的很好的服務。有關ERPpeek的更多細節請見 GitHub。
本文的目標是學習外部 API 如何運做以及它們能作些什麼。一開始咱們經過一個簡單的Python XML-RPC客戶端來進行探討,但外部 API 可用於其它編程語言。事實上官方文檔中包含了Java, PHP和Ruby的代碼示例。
有不少庫可處理XML-RPC或JSON-RPC,有些是通用的,有些僅適用於 Odoo。咱們使用了一個指定庫OdooRPC。
以上咱們就完結了本文有關編程 API 和業務邏輯的學習。是時候深刻視圖和用戶界面了。在下一篇文章中,咱們進一步學習網頁客戶端所提供的後臺視圖和用戶體驗。