第六章:從頭創建視圖?
警告
在開始本章之前,強烈建議您完成 第三章:字段和視圖 。第3章介紹的概念,包括視圖和示例,對于理解本章所涉及的內容至關重要。
讓我們看看如何完全從頭開始創建一個新視圖。從某種意義上說,這并不是很難,但是沒有真正好的資源來說明如何做到這一點。請注意,大多數情況應該通過定制現有視圖或使用客戶端操作來解決。
在這個練習中,我們假設我們想創建一個“畫廊”視圖,它是一個視圖,可以用圖像字段表示一組記錄。在我們的Awesome Tshirt場景中,我們希望能夠看到一組T恤衫的圖像。
這個問題當然可以通過看板視圖來解決,但這意味著我們不能在同一個操作中同時使用普通看板視圖和畫廊視圖。
讓我們創建一個圖庫視圖。每個圖庫視圖將由其 arch 中的 image_field
屬性定義:
<gallery image_field="some_field"/>
為了完成本章的任務,您需要安裝awesome_gallery插件。該插件包含必要的服務器文件以添加新視圖。
目標

本章節的每個練習的解決方案都托管在 官方Odoo教程存儲庫 上。
1. 創建一個 Hello World 視圖?
第一步是創建一個帶有簡單組件的JavaScript實現。
Exercise
在
static/src
中創建gallery_view.js
、gallery_controller.js
和gallery_controller.xml
文件。在
gallery_controller.js
中實現一個簡單的 hello world 組件。在
gallery_view.js
中,導入控制器,創建視圖對象,并將其注冊到視圖注冊表中,名稱為gallery
。在訂單操作中添加
gallery
作為一種視圖類型。確保在切換到圖庫視圖時,您可以看到您的hello world組件。


2. 使用布局組件?
到目前為止,我們的畫廊視圖看起來不像標準視圖。讓我們使用“Layout”組件來擁有其他視圖的標準功能。
Exercise
導入
Layout
組件并將其添加到GalleryController
的components
中。更新模板以使用
Layout
。它需要一個display
屬性,可以在props.display
中找到。

3. 解析 arch?
目前,我們的圖庫視圖還沒有做太多事情。讓我們從閱讀視圖中包含的結構信息開始。
解析arch的過程通常使用 ArchParser
完成,每個視圖都有特定的 ArchParser
。它繼承了通用的 XMLParser
類。
Example
這是一個 ArchParser 可能看起來像的例子:
import { XMLParser } from "@web/core/utils/xml";
export class GraphArchParser extends XMLParser {
parse(arch, fields) {
const result = {};
this.visitXML(arch, (node) => {
...
});
return result;
}
}
Exercise
在單獨的文件中創建
ArchParser
類。它可以繼承@web/core/utils/xml
中的XMLParser
。使用它來讀取
image_field
信息。更新
gallery
視圖代碼,將其添加到控制器接收的 props 中。
注解
這樣做可能有點過度設計,因為我們基本上只需要從arch中讀取一個屬性,但這是每個Odoo視圖都使用的設計,因為它讓我們將一些前期處理從控制器中提取出來。
另請參閱
4. 加載一些數據?
現在讓我們獲取一些真實數據。
Exercise
在
GalleryController
中添加loadImages(domain) {...}
方法。它應該從 orm 服務執行webSearchRead
調用,以獲取與該域相對應的記錄,并使用在 props 中接收到的imageField
。修改
setup
代碼,在onWillStart
和onWillUpdateProps
鉤子中調用該方法。修改模板以在“Layout”組件的默認插槽中顯示數據。
注解
加載數據的代碼將在下一個練習中移入適當的模型中。

5. 重新組織代碼?
真正的視圖會更加有組織。在這個例子中可能有些過度,但這是為了學習如何在Odoo中構建代碼結構。此外,這將更好地適應不斷變化的需求。
Exercise
將所有模型代碼移動到自己的
GalleryModel
類中。將所有渲染代碼移動到
GalleryRenderer
組件中。調整
GalleryController
和gallery_view
以使其正常工作。
6. 顯示圖片?
Exercise
如果設置了 image_field
,請更新渲染器以漂亮地顯示圖像。如果 image_field
為空,請顯示一個空框。

7. 點擊后切換到表單視圖?
Exercise
更新渲染器以響應對圖像的單擊并切換到表單視圖。您可以使用操作服務中的 switchView
函數。
另請參閱
8. 添加一個可選的工具提示?
鼠標懸停時提供一些額外的信息是有用的。
Exercise
更新代碼以允許在arch上添加一個可選的附加屬性:
<gallery image_field="some_field" tooltip_field="some_other_field"/>
鼠標懸停時,顯示工具提示字段的內容。如果該字段是字符字段、數字字段或many2one字段,則應該可以正常工作。
更新訂單畫廊視圖,將客戶添加為工具提示字段。

另請參閱
9. 添加分頁功能?
Exercise
讓我們在控制面板上添加一個分頁器,并像在普通的Odoo視圖中一樣管理所有分頁。請注意,這是非常困難的。

另請參閱
10. 驗證視圖?
到目前為止,我們已經擁有了一個漂亮且有用的視圖。但在實際應用中,我們可能會遇到用戶錯誤編碼其圖庫視圖的 arch
的問題:它目前只是一個非結構化的 XML 片段。
讓我們添加一些驗證!在Odoo中,XML文檔可以使用RN文件 (Relax NG文件) 進行描述,然后進行驗證。
Exercise
添加一個描述當前語法的 RNG 文件:
必填屬性
image_field
。一個可選屬性:
tooltip_field
。
添加一些代碼,確保所有視圖都根據此 RNG 文件進行驗證。
順便提一下,確保
image_field
和tooltip_field
是當前模型中的字段。
由于驗證 RNG 文件并不容易,這里提供了一個代碼片段以幫助您:
# -*- coding: utf-8 -*-
import logging
import os
from lxml import etree
from odoo.loglevels import ustr
from odoo.tools import misc, view_validation
_logger = logging.getLogger(__name__)
_viewname_validator = None
@view_validation.validate('viewname')
def schema_viewname(arch, **kwargs):
""" Check the gallery view against its schema
:type arch: etree._Element
"""
global _viewname_validator
if _viewname_validator is None:
with misc.file_open(os.path.join('modulename', 'rng', 'viewname.rng')) as f:
_viewname_validator = etree.RelaxNG(etree.parse(f))
if _viewname_validator.validate(arch):
return True
for error in _viewname_validator.error_log:
_logger.error(ustr(error))
return False
另請參閱