第六章:從頭創建視圖?

警告

在開始本章之前,強烈建議您完成 第三章:字段和視圖 。第3章介紹的概念,包括視圖和示例,對于理解本章所涉及的內容至關重要。

讓我們看看如何完全從頭開始創建一個新視圖。從某種意義上說,這并不是很難,但是沒有真正好的資源來說明如何做到這一點。請注意,大多數情況應該通過定制現有視圖或使用客戶端操作來解決。

在這個練習中,我們假設我們想創建一個“畫廊”視圖,它是一個視圖,可以用圖像字段表示一組記錄。在我們的Awesome Tshirt場景中,我們希望能夠看到一組T恤衫的圖像。

這個問題當然可以通過看板視圖來解決,但這意味著我們不能在同一個操作中同時使用普通看板視圖和畫廊視圖。

讓我們創建一個圖庫視圖。每個圖庫視圖將由其 arch 中的 image_field 屬性定義:

<gallery image_field="some_field"/>

為了完成本章的任務,您需要安裝awesome_gallery插件。該插件包含必要的服務器文件以添加新視圖。

目標

../../../_images/overview2.png

本章節的每個練習的解決方案都托管在 官方Odoo教程存儲庫 上。

1. 創建一個 Hello World 視圖?

第一步是創建一個帶有簡單組件的JavaScript實現。

Exercise

  1. static/src 中創建 gallery_view.js 、 gallery_controller.jsgallery_controller.xml 文件。

  2. gallery_controller.js 中實現一個簡單的 hello world 組件。

  3. gallery_view.js 中,導入控制器,創建視圖對象,并將其注冊到視圖注冊表中,名稱為 gallery 。

  4. 在訂單操作中添加 gallery 作為一種視圖類型。

  5. 確保在切換到圖庫視圖時,您可以看到您的hello world組件。

../../../_images/view_button.png ../../../_images/new_view.png

2. 使用布局組件?

到目前為止,我們的畫廊視圖看起來不像標準視圖。讓我們使用“Layout”組件來擁有其他視圖的標準功能。

Exercise

  1. 導入 Layout 組件并將其添加到 GalleryControllercomponents 中。

  2. 更新模板以使用 Layout 。它需要一個 display 屬性,可以在 props.display 中找到。

../../../_images/layout1.png

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

  1. 在單獨的文件中創建 ArchParser 類。它可以繼承 @web/core/utils/xml 中的 XMLParser 。

  2. 使用它來讀取 image_field 信息。

  3. 更新 gallery 視圖代碼,將其添加到控制器接收的 props 中。

注解

這樣做可能有點過度設計,因為我們基本上只需要從arch中讀取一個屬性,但這是每個Odoo視圖都使用的設計,因為它讓我們將一些前期處理從控制器中提取出來。

4. 加載一些數據?

現在讓我們獲取一些真實數據。

Exercise

  1. GalleryController 中添加 loadImages(domain) {...} 方法。它應該從 orm 服務執行 webSearchRead 調用,以獲取與該域相對應的記錄,并使用在 props 中接收到的 imageField 。

  2. 修改 setup 代碼,在 onWillStartonWillUpdateProps 鉤子中調用該方法。

  3. 修改模板以在“Layout”組件的默認插槽中顯示數據。

注解

加載數據的代碼將在下一個練習中移入適當的模型中。

../../../_images/gallery_data.png

5. 重新組織代碼?

真正的視圖會更加有組織。在這個例子中可能有些過度,但這是為了學習如何在Odoo中構建代碼結構。此外,這將更好地適應不斷變化的需求。

Exercise

  1. 將所有模型代碼移動到自己的 GalleryModel 類中。

  2. 將所有渲染代碼移動到 GalleryRenderer 組件中。

  3. 調整 GalleryControllergallery_view 以使其正常工作。

6. 顯示圖片?

Exercise

如果設置了 image_field ,請更新渲染器以漂亮地顯示圖像。如果 image_field 為空,請顯示一個空框。

../../../_images/tshirt_images.png

7. 點擊后切換到表單視圖?

Exercise

更新渲染器以響應對圖像的單擊并切換到表單視圖。您可以使用操作服務中的 switchView 函數。

8. 添加一個可選的工具提示?

鼠標懸停時提供一些額外的信息是有用的。

Exercise

  1. 更新代碼以允許在arch上添加一個可選的附加屬性:

    <gallery image_field="some_field" tooltip_field="some_other_field"/>
    
  2. 鼠標懸停時,顯示工具提示字段的內容。如果該字段是字符字段、數字字段或many2one字段,則應該可以正常工作。

  3. 更新訂單畫廊視圖,將客戶添加為工具提示字段。

../../../_images/image_tooltip.png

9. 添加分頁功能?

Exercise

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

../../../_images/pagination.png

10. 驗證視圖?

到目前為止,我們已經擁有了一個漂亮且有用的視圖。但在實際應用中,我們可能會遇到用戶錯誤編碼其圖庫視圖的 arch 的問題:它目前只是一個非結構化的 XML 片段。

讓我們添加一些驗證!在Odoo中,XML文檔可以使用RN文件 (Relax NG文件) 進行描述,然后進行驗證。

Exercise

  1. 添加一個描述當前語法的 RNG 文件:

    • 必填屬性 image_field 。

    • 一個可選屬性: tooltip_field 。

  2. 添加一些代碼,確保所有視圖都根據此 RNG 文件進行驗證。

  3. 順便提一下,確保 image_fieldtooltip_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