警告
該教程需要 已安裝odoo
開啟/停止Odoo服務
odoo使用用戶端/伺服器架構,用戶端是通過RPC(遠端過程調用協定)通路Odoo服務的web浏覽器。
業務邏輯和擴充通常在伺服器端執行,盡管支援用戶端功能(如,想互動式地圖的新資料表示)可以添加到用戶端。
為了啟動伺服器,在shell内簡單的調用指令Odoo,如果必要添加檔案的完整路徑
伺服器按Ctrl-C兩次從終端停止,或殺死相應的OS程序。
建立一個Odoo子產品
伺服器和用戶端擴充都打包為可選擇的加載在資料庫中的子產品。
Odoo子產品既可以添加新的業務邏輯到Odoo系統,也可以修改和擴充現有的業務邏輯:一個子產品可以被建立為Odoo通用會計支援添加你的國家的會計準則,而下一個子產品,增加了對公車的實時可視化支援。
是以,odoo的一切都随着子產品的開始結束而開始結束。
1.子產品的組成
一個Odoo子產品可以包含多個元素:
業務對象:
聲明為Python的類,這些資源是自動持續的,通過基于配置的Odoo。
資料檔案
XML或CSV檔案聲明中繼資料(視圖或工作流),配置資料(子產品參數化),示範資料和更多
Web controllers
處理Web浏覽器的請求
靜态web資料
Web界面或網站使用的圖檔,CSS或JS檔案
2.子產品結構
每個子產品是子產品目錄内的目錄。子產品目錄通過–addons-path 選項被指定。
提示
大多數指令行選項也可以使用配置檔案來設定
odoo子產品是通過它的manifest聲明的。一個子產品也是一個帶
__init__.py
的Python包,包含子產品中各種Python檔案的導入說明。
例如,如果子產品有一個
mymodule.py
,
__init__.py
應該包含檔案:
from . import mymodule
Odoo提供了一種機制來幫助建立一個新的子產品,odoo-bin有一子指令scaffold 建立一個空的子產品:
odoo-bin scaffold <module name> <where to put it>
該指令為子產品建立一個子目錄,并自動為子產品建立一堆标準檔案。其中大部分隻包含注釋代碼或xml。這些檔案的使用将在本教程中解釋。
練習
子產品建立
使用指令行上建立一個空的子產品Open Academy,并安裝在Odoo上。
1. 調用指令odoo-bin scaffold openacademy odoo/addons
2. 将manifest檔案更新到子產品。
3. 不要改變其他檔案。
openacademy/__manifest__.py::
# -*- coding: utf-8 -*-
{
'name': "Open Academy",
'summary': """Manage trainings""",
'description': """
Open Academy module for managing trainings:
- training courses
- training sessions
- attendees registration
""",
'author': "My Company",
'website': "http://www.yourcompany.com",
# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/master/odoo/addons/base/module/module_data.xml
# for the full list
'category': 'Test',
'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['base'],
# always loaded
'data': [
# 'security/ir.model.access.csv',
'templates.xml',
],
# only loaded in demonstration mode
'demo': [
'demo.xml',
],
}
openacademy/__init__.py:
# -*- coding: utf-8 -*-
from . import controllers
from . import models
openacademy/controllers.py:
# -*- coding: utf-8 -*-
from odoo import http
# class Openacademy(http.Controller):
# @http.route('/openacademy/openacademy/', auth='public')
# def index(self, **kw):
# return "Hello, world"
# @http.route('/openacademy/openacademy/objects/', auth='public')
# def list(self, **kw):
# return http.request.render('openacademy.listing', {
# 'root': '/openacademy/openacademy',
# 'objects': http.request.env['openacademy.openacademy'].search([]),
# })
# @http.route('/openacademy/openacademy/objects/<model("openacademy.openacademy"):obj>/', auth='public')
# def object(self, obj, **kw):
# return http.request.render('openacademy.object', {
# 'object': obj
# })
openacademy/demo.xml:
<odoo>
<data>
<!-- -->
<!-- <record id="object0" model="openacademy.openacademy"> -->
<!-- <field name="name">Object 0</field> -->
<!-- </record> -->
<!-- -->
<!-- <record id="object1" model="openacademy.openacademy"> -->
<!-- <field name="name">Object 1</field> -->
<!-- </record> -->
<!-- -->
<!-- <record id="object2" model="openacademy.openacademy"> -->
<!-- <field name="name">Object 2</field> -->
<!-- </record> -->
<!-- -->
<!-- <record id="object3" model="openacademy.openacademy"> -->
<!-- <field name="name">Object 3</field> -->
<!-- </record> -->
<!-- -->
<!-- <record id="object4" model="openacademy.openacademy"> -->
<!-- <field name="name">Object 4</field> -->
<!-- </record> -->
<!-- -->
</data>
</odoo>
openacademy/models.py:
# -*- coding: utf-8 -*-
from odoo import models, fields, api
# class openacademy(models.Model):
# _name = 'openacademy.openacademy'
# name = fields.Char()
openacademy/security/ir.model.access.csv:
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_openacademy_openacademy,openacademy.openacademy,model_openacademy_openacademy,,,,,
openacademy/templates.xml:
<odoo>
<data>
<!-- <template id="listing"> -->
<!-- <ul> -->
<!-- <li t-foreach="objects" t-as="object"> -->
<!-- <a t-attf-href="{{ root }}/objects/{{ object.id }}"> -->
<!-- <t t-esc="object.display_name"/> -->
<!-- </a> -->
<!-- </li> -->
<!-- </ul> -->
<!-- </template> -->
<!-- <template id="object"> -->
<!-- <h1><t t-esc="object.display_name"/></h1> -->
<!-- <dl> -->
<!-- <t t-foreach="object._fields" t-as="field"> -->
<!-- <dt><t t-esc="field"/></dt> -->
<!-- <dd><t t-esc="object[field]"/></dd> -->
<!-- </t> -->
<!-- </dl> -->
<!-- </template> -->
</data>
</odoo>
3.對象關系映射
Odoo的一個關鍵組成部分是ORM層。這一層可以避免手工編寫大多數SQL并提供了可擴充性和安全性的服務。
業務對象被聲明為Python類擴充模型,該模型将它們內建到自動持久化系統中。
模型可以通過在它們的定義中設定一些屬性進行配置。最重要的屬性是_name,這是必要的,在Odoo中定義系統模型的名字。這裡是一個模型的最小完整定義:
from odoo import models
class MinimalModel(models.Model):
_name = 'test.model'
4.模型檔案
字段用于定義模型可以存儲和在哪裡。字段被定義為模型類的屬性:
from odoo import models, fields
class LessMinimalModel(models.Model):
_name = 'test.model2'
name = fields.Char()
(1) 共同屬性
就像模型本身一樣,它的字段可以通過将配置屬性作為參數來配置:
一些屬性在所有領域都可用,這裡是最常見的:
string (unicode, default: field's name)
使用者界面中字段的标簽(使用者可見)。
required (bool, default: False)
如果為TRUE,字段不能為空,則必須具有預設值或在建立記錄時始終給予值。
help (unicode, default: '')
Long-form, 為使用者提供了一個幫助提示。
index (bool, default: False)
要求 Odoo建立列上的資料庫索引。
(2) 簡單字段
有兩種類型的字段:“simple”字段,它們直接存儲在模型表中的原子值,以及連接配接記錄(同一模型或不同模型)的“relational”字段。
簡單字段的例子:Boolean, Date, Char.
(3) 保留字段
Odoo在所有模型創造了一些字段。這些字段由系統管理,不應寫入。如果有用或必要,它們可以被讀取:
id (Id)
模型中記錄的唯一辨別符。
create_date (Datetime)
記錄的建立日期.
create_uid (Many2one)
建立記錄的使用者。
write_date (Datetime)
記錄的最後修改日期。
write_uid (Many2one)
最後修改記錄的使用者。
(4) 特殊字段
預設情況下,Odoo所有的模型也需要一個name字段,以便各種顯示和搜尋行為。被用于這些目的的字段能通過設定
_rec_name
重寫。
練習
定義一個模型
在openacademy 子產品裡 定義一個新的資料模型Course ,course 有标題(title)和描述(description) ,必須有标題
編輯openacademy/models/models.py檔案,包含到Course 類中。
openacademy/models.py:
from odoo import models, fields, api
class Course(models.Model):
_name = 'openacademy.course'
name = fields.Char(string="Title", required=True)
description = fields.Text()
5.資料字段
雖然使用Python代碼定制行為,但子產品的值的一部分在加載時設定的資料中。
提示
一些子產品的存在隻為資料添加到Odoo。
子產品資料通過資料檔案,帶有
<record>
元素的xml檔案聲明。每個元素建立或更新資料庫記錄。
<odoo>
<data>
<record model="{model name}" id="{record identifier}">
<field name="{a field name}">{a value}</field>
</record>
</data>
</odoo>
· model是用于記錄Odoo模型名稱。
· id是一個外部辨別符,它允許引用到記錄(而不必知道它的内部資料庫辨別符)。
·
<field>
元素的name是模型中字段的name(例如描述)。他們的body是字段的值。
必須在清單檔案中聲明要加載的資料檔案。它們可以在“data”清單中(總是加載)或在“demo”清單中聲明(僅在示範模式下加載)。
練習
定義示範資料 ,用示範課程建立示範資料,完善課程模式。
編輯openacademy/demo/demo.xml檔案來包含一些資料
openacademy/demo.xml:
<odoo>
<data>
<record model="openacademy.course" id="course0">
<field name="name">Course 0</field>
<field name="description">Course 0's description
Can have multiple lines
</field>
</record>
<record model="openacademy.course" id="course1">
<field name="name">Course 1</field>
<!-- no description for this one -->
</record>
<record model="openacademy.course" id="course2">
<field name="name">Course 2</field>
<field name="description">Course 2's description</field>
</record>
</data>
</odoo>
-
Actions和Menus
動作和菜單是資料庫中的正常記錄,通常通過資料檔案聲明。動作可以用三種方式觸發:
(1) 通過點選菜單項(連結到特定的動作)
(2) 通過點選視圖的按鈕 (如果被連接配接到動作)
(3) 作為對象的上下文操作
因為菜單的聲明有點複雜,有一個
快捷方式來更容易地聲明 ir.ui.menu 并連結它到相關的action。<menuitem>
<record model="ir.actions.act_window" id="action_list_ideas">
<field name="name">Ideas</field>
<field name="res_model">idea.idea</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_ideas" parent="menu_root" name="Ideas" sequence="10"
action="action_list_ideas"/>
危險
必須在xml檔案的相應菜單前聲明該操作。
資料檔案是按順序執行的,在菜單能建立前,動作的id必須存在于資料庫中
-
練習
定義新的菜單入口
在OpenAcademy 菜單入口定義新的菜單入口來通路課程,使用者應該能夠:
· 顯示所有課程清單
· 建立/修改課程
(1) 建立openacademy/views/openacademy.xml,附帶一個action和觸發action的菜單。
(2) 把它添加到
的data清單。
openacademy/__manifest__.py
openacademy/__manifest__.py
'data': [
# 'security/ir.model.access.csv',
'templates.xml',
'views/openacademy.xml',
],
# only loaded in demonstration mode
'demo': [
----------
openacademy/views/openacademy.xml:
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<!-- window action -->
<!--
The following tag is an action definition for a "window action",
that is an action opening a view or a set of views
-->
<record model="ir.actions.act_window" id="course_list_action">
<field name="name">Courses</field>
<field name="res_model">openacademy.course</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create the first course
</p>
</field>
</record>
<!-- top level menu: no parent -->
<menuitem id="main_openacademy_menu" name="Open Academy"/>
<!-- A first level in the left side menu is needed
before using action= attribute -->
<menuitem id="openacademy_menu" name="Open Academy"
parent="main_openacademy_menu"/>
<!-- the following menuitem should appear *after*
its parent openacademy_menu and *after* its
action course_list_action -->
<menuitem id="courses_menu" name="Courses" parent="openacademy_menu"
action="course_list_action"/>
<!-- Full id location:
action="openacademy.course_list_action"
It is not required when it is the same module -->
</data>
</odoo>
基本視圖
視圖定義顯示模型記錄的方式。每種類型的視圖表示一個可視化模式(一個記錄清單,一個聚合的圖形,…)。視圖可以被要求通過他們的類型(例如類合作夥伴名單)或專門通過它們的ID的通用要求,具有正确的類型和優先級最低的視圖将被使用(是以各類型優先級最低的視圖是預設視圖為型)。
視圖繼承允許改變在别處聲明的視圖(添加或删除内容)。
-
通用視圖聲明
視圖被聲明為ir.ui.view模型的記錄,視圖類型由arch字段的根元素說明:
<record model="ir.ui.view" id="view_id">
<field name="name">view.name</field>
<field name="model">object_name</field>
<field name="priority" eval="16"/>
<field name="arch" type="xml">
<!-- view content: <form>, <tree>, <graph>, ... -->
</field>
</record>
危險
視圖的内容是XML.是以,arch字段必須聲明為
,以便正确解析。
type="xml"
2.樹視圖
樹視圖,也被稱為清單視圖。以表單形式顯示記錄。
根元素是
<tree>
,樹視圖的最簡單形式隻列出了表中顯示的所有字段(每個字段列):
<tree string="Idea list">
<field name="name"/>
<field name="inventor_id"/>
</tree>
3.表單視圖
表單被用于建立和編輯單個記錄。
根元素是
<form>
,它們由高層次結構元素(groups、notebooks)和互動元素(按鈕和字段)組成:
<form string="Idea form">
<group colspan="4">
<group colspan="2" col="2">
<separator string="General stuff" colspan="2"/>
<field name="name"/>
<field name="inventor_id"/>
</group>
<group colspan="2" col="2">
<separator string="Dates" colspan="2"/>
<field name="active"/>
<field name="invent_date" readonly="1"/>
</group>
<notebook colspan="4">
<page string="Description">
<field name="description" nolabel="1"/>
</page>
</notebook>
<field name="state"/>
</group>
</form>
練習
使用XML制作form視圖
給Course 對象建立form視圖,資料應該顯示:Course 的name和description。
openacademy/views/openacademy.xml:
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record model="ir.ui.view" id="course_form_view">
<field name="name">course.form</field>
<field name="model">openacademy.course</field>
<field name="arch" type="xml">
<form string="Course Form">
<sheet>
<group>
<field name="name"/>
<field name="description"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- window action -->
<!--
The following tag is an action definition for a "window action",
練習
Notebooks
在Course 表單視圖裡,将“description”字段置于頁籤之下,以便稍後添加其他頁籤,包含附加資訊。
如下修改Course 表單視圖:
openacademy/views/openacademy.xml
<sheet>
<group>
<field name="name"/>
</group>
<notebook>
<page string="Description">
<field name="description"/>
</page>
<page string="About">
This is an example of notebooks
</page>
</notebook>
</sheet>
</form>
</field>
表單視圖也可以使用純HTML來進行更靈活的布局:
<form string="Idea Form">
<header>
<button string="Confirm" type="object" name="action_confirm"
states="draft" class="oe_highlight" />
<button string="Mark as done" type="object" name="action_done"
states="confirmed" class="oe_highlight"/>
<button string="Reset to draft" type="object" name="action_draft"
states="confirmed,done" />
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Idea Name" />
<h1><field name="name" /></h1>
</div>
<separator string="General" colspan="2" />
<group colspan="2" col="2">
<field name="description" placeholder="Idea description..." />
</group>
</sheet>
</form>
4.搜尋視圖
搜尋視圖自定義與清單視圖關聯的搜尋字段(以及其他聚合視圖)。它們的根元素是
<search>
,它們由定義哪些字段可以被搜尋的字段組成:
<search>
<field name="name"/>
<field name="inventor_id"/>
</search>
如果模型沒有搜尋視圖,Odoo産生一個隻允許用名稱字段檢索的搜尋視圖。
練習
搜尋視圖
允許根據他們的标題或描述來搜尋課程。
openacademy/views/openacademy.xml
</field>
</record>
<record model="ir.ui.view" id="course_search_view">
<field name="name">course.search</field>
<field name="model">openacademy.course</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="description"/>
</search>
</field>
</record>
<!-- window action -->
<!--
The following tag is an action definition for a "window action",
模型之間的關系
例如,銷售訂單記錄與包含客戶資料的客戶機記錄有關,它還與銷售訂單線記錄有關。
練習
建立一個session 模型
對于Open Academy 子產品,我們考慮一個session 模型:一個session 是一個給定的時間給定的觀衆在一個給定的時間發生的課程。
建立session 模型。session 具有名稱、開始日期、持續時間和若幹個座位。添加一個動作和菜單項來顯示它們。通過菜單項使新模型可見。
1、在openacademy/models/models.py中建立session 類
2、在openacademy/view/openacademy.xml中給session 對象添加入口
openacademy/models.py
name = fields.Char(string="Title", required=True)
description = fields.Text()
class Session(models.Model):
_name = 'openacademy.session'
name = fields.Char(required=True)
start_date = fields.Date()
duration = fields.Float(digits=(, ), help="Duration in days")
seats = fields.Integer(string="Number of seats")
openacademy/views/openacademy.xml
<!-- Full id location:
action="openacademy.course_list_action"
It is not required when it is the same module -->
<!-- session form view -->
<record model="ir.ui.view" id="session_form_view">
<field name="name">session.form</field>
<field name="model">openacademy.session</field>
<field name="arch" type="xml">
<form string="Session Form">
<sheet>
<group>
<field name="name"/>
<field name="start_date"/>
<field name="duration"/>
<field name="seats"/>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="session_list_action">
<field name="name">Sessions</field>
<field name="res_model">openacademy.session</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="session_menu" name="Sessions"
parent="openacademy_menu"
action="session_list_action"/>
</data>
</odoo>
注意
digits=(6, 2)指定浮點數的精度:6是數字的總數,而2是小數點後的位數。請注意,它的結果在小數點前是最大值4位數字。
1.關系字段
關系字段連結記錄,包括相同的模型(層次結構)或不同模型之間的連結記錄。
關系字段類型:
(1)
Many2one(other_model, ondelete='set null')
到另一個對象的簡單連結:
(2)
One2many(other_model, related_field)
一個虛拟的關系,一個many2one的逆。一個one2many作為容器的記錄,通路的結果是一個(可能為空)的記錄集:
for other in foo.other_ids:
print other.name
危險
因為One2many 是一個虛拟的關系,在other_model裡必須有一個Many2one字段,name必須是related_field 。
(3)
Many2many(other_model)
雙向多重關系,一方的任何記錄都可以與另一方的任何記錄有關。作為記錄的容器,通路它也會導緻一組可能空的記錄:
for other in foo.other_ids:
print other.name
練習
Many2one 關系
使用Many2one ,修改Course 和Session 模型,反映他們與其他模型的關系:
· course有一個responsible 使用者,該字段的值是内模組化型res.users的一個記錄。
· Session 有一個instructor,該字段的值是内模組化型res.partner的一個記錄。
· 一個session被連接配接到一個course,該字段的值是模型openacademy.course的一個記錄,并且是必須的。
· 更新視圖
添加Many2one字段到模型裡, 并将它們添加到視圖中。
openacademy/models.py
name = fields.Char(string="Title", required=True)
description = fields.Text()
responsible_id = fields.Many2one('res.users',
ondelete='set null', string="Responsible", index=True)
class Session(models.Model):
_name = 'openacademy.session'
----------
start_date = fields.Date()
duration = fields.Float(digits=(, ), help="Duration in days")
seats = fields.Integer(string="Number of seats")
instructor_id = fields.Many2one('res.partner', string="Instructor")
course_id = fields.Many2one('openacademy.course',
ondelete='cascade', string="Course", required=True)
openacademy/views/openacademy.xml
<sheet>
<group>
<field name="name"/>
<field name="responsible_id"/>
</group>
<notebook>
<page string="Description">
----------
</field>
</record>
<!-- override the automatically generated list view for courses -->
<record model="ir.ui.view" id="course_tree_view">
<field name="name">course.tree</field>
<field name="model">openacademy.course</field>
<field name="arch" type="xml">
<tree string="Course Tree">
<field name="name"/>
<field name="responsible_id"/>
</tree>
</field>
</record>
<!-- window action -->
<!--
The following tag is an action definition for a "window action",
----------
<form string="Session Form">
<sheet>
<group>
<group string="General">
<field name="course_id"/>
<field name="name"/>
<field name="instructor_id"/>
</group>
<group string="Schedule">
<field name="start_date"/>
<field name="duration"/>
<field name="seats"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- session tree/list view -->
<record model="ir.ui.view" id="session_tree_view">
<field name="name">session.tree</field>
<field name="model">openacademy.session</field>
<field name="arch" type="xml">
<tree string="Session Tree">
<field name="name"/>
<field name="course_id"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="session_list_action">
<field name="name">Sessions</field>
<field name="res_model">openacademy.session</field>
練習
one2many 逆關系
使用one2many逆關系字段,修改模型,以反映course和session之間的關系
修改course類 ,在course表單視圖添加該字段。
openacademy/models.py
responsible_id = fields.Many2one('res.users',
ondelete='set null', string="Responsible", index=True)
session_ids = fields.One2many(
'openacademy.session', 'course_id', string="Sessions")
class Session(models.Model):
openacademy/views/openacademy.xml
<page string="Description">
<field name="description"/>
</page>
<page string="Sessions">
<field name="session_ids">
<tree string="Registered sessions">
<field name="name"/>
<field name="instructor_id"/>
</tree>
</field>
</page>
</notebook>
</sheet>
練習
多重many2many 關系
利用關系字段many2many,修改session模型 ,将一組人與每一個課程關聯。出席者将通過夥伴的記錄作為代表,是以我們将與内置的模型res.partner關聯。相應地調整視圖。
修改session類,并添加到表單視圖
openacademy/models.py
instructor_id = fields.Many2one('res.partner', string="Instructor")
course_id = fields.Many2one('openacademy.course',
ondelete='cascade', string="Course", required=True)
attendee_ids = fields.Many2many('res.partner', string="Attendees")
openacademy/views/openacademy.xml
<field name="seats"/>
</group>
</group>
<label for="attendee_ids"/>
<field name="attendee_ids"/>
</sheet>
</form>
</field>
繼承
1.模型繼承
Odoo提供兩繼承機制,以子產品化的方式擴充現有的模型。
第一繼承機制允許子產品修改在其他子產品中定義的模型的行為:
· 添加字段到子產品
· 重寫模型上字段的定義
· 向模型添加限制,
· 向模型添加方法,
· 在模型上重寫現有方法。
第二繼承機制(委托)允許将模型的每個記錄與父模型中的記錄連接配接起來,并提供對父記錄字段的透明通路。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQ3chVEa0V3bT9CX5RXa2Fmcn9CXwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwleBpXTz0keOFTT6hVdsdUZwZlMkZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jN4QTNzITNyEDNxUDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
2.視圖繼承
與其修改現有的視圖(通過重寫他們),Odoo提供的視圖繼承讓子“拓展”視圖應用在頂部的根視圖,并可以從父内容添加或删除。
拓展視圖使用inherit_id字段參考它的父視圖。而不是單一的,arch字段是由任意數量的xpath元素選擇組成,并改變它們父視圖的内容的視圖:
<!-- improved idea categories list -->
<record id="idea_category_list2" model="ir.ui.view">
<field name="name">id.category.list2</field>
<field name="model">idea.category</field>
<field name="inherit_id" ref="id_category_list"/>
<field name="arch" type="xml">
<!-- find field description and add the field
idea_ids after it -->
<xpath expr="//field[@name='description']" position="after">
<field name="idea_ids" string="Number of ideas"/>
</xpath>
</field>
</record>
·
expr
在父視圖中選擇單個元素的XPath表達式。如果不比對任何元素或多于一個元素,則引發錯誤
·
position
用于比對元素的操作: