#### 高級視圖
[TOC]
##### 樹視圖
樹視圖可以采用輔助屬性來進一步自定義其行為:
`decoration-{$name}`
允許根據對應記錄屬性修改行的文本風格。對于每個記錄,將使用記錄的屬性作為上下文來計算表達式,如果值為`true`,則將相應的樣式應用于行。其他上下文值為`uid`(當前用戶的標識)和`current_date`(`yyyy-MM-dd`格式的當前日期字符串)。`{$name}`可以是`bf(font-weight:bold)`、`it(font-style:italic)`或任何bootstrap上下文顏色(`danger,info,muted,primary,success,warning`)
~~~
<tree string="Idea Categories" decoration-info="state=='draft'"
decoration-danger="state=='trashed'">
<field name="name"/>
<field name="state"/>
</tree>
~~~
`editable`
`top`和`bottom`使樹視圖可直接編輯(而不需要通過表單視圖),其值就是新行出現的位置。
> 練習列表著色
> 編輯授課的樹視圖,使得持續時間少于5天的授課以藍色顯示,持續時間超過15天的授課以紅色顯示。編輯授課的樹視圖:
`openacademy/views/openacademy.xml`
~~~
<field name="name">session.tree</field>
<field name="model">openacademy.session</field>
<field name="arch" type="xml">
<tree string="Session Tree" decoration-info="duration<5" decoration-danger="duration>15">
<field name="name"/>
<field name="course_id"/>
<field name="duration" invisible="1"/>
<field name="taken_seats" widget="progressbar"/>
</tree>
</field>
~~~
##### 日歷
將記錄顯示為日歷活動,通過將根元素設置為`<calendar>`,主要的屬性有:
`color`
字段的名稱通過顏色來區分。顏色會自動分配給事件,但相同顏色定義的事件(`@color`屬性有相同值的記錄)將被使用相同的顏色。
`date_start`
記錄中用于保存事件開始日期/時間的字段。
`date_stop`(可選)
記錄中用于保存時間結束日期/時間的字段。
為每個日歷事件定義標簽的字段
~~~
<calendar string="Ideas" date_start="invent_date" color="inventor_id">
<field name="name"/>
</calendar>
~~~
> 練習日歷視圖
> 給授課模型添加一個日歷視圖,使用戶可以查看與開放學院相關聯的事件。
>
> * 添加一個計算字段`end_date`,通過`start_date`和`duration`計算獲得。
> * 反函數使字段可寫,并允許在日歷視圖中移動授課(通過拖放操作)
> * 向授課模型添加日歷視圖
> * 添加日歷視圖到授課模型的動作中
`openacademy/models.py`
~~~
# -*- coding: utf-8 -*-
from datetime import timedelta
from odoo import models, fields, api, exceptions
class Course(models.Model):
~~~
~~~
attendee_ids = fields.Many2many('res.partner', string="Attendees")
taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')
end_date = fields.Date(string="End Date", store=True,
compute='_get_end_date', inverse='_set_end_date')
@api.depends('seats', 'attendee_ids')
def _taken_seats(self):
~~~
~~~
},
}
@api.depends('start_date', 'duration')
def _get_end_date(self):
for r in self:
if not (r.start_date and r.duration):
r.end_date = r.start_date
continue
# Add duration to start_date, but: Monday + 5 days = Saturday, so
# subtract one second to get on Friday instead
start = fields.Datetime.from_string(r.start_date)
duration = timedelta(days=r.duration, seconds=-1)
r.end_date = start + duration
def _set_end_date(self):
for r in self:
if not (r.start_date and r.end_date):
continue
# Compute the difference between dates, but: Friday - Monday = 4 days,
# so add one day to get 5 days instead
start_date = fields.Datetime.from_string(r.start_date)
end_date = fields.Datetime.from_string(r.end_date)
r.duration = (end_date - start_date).days + 1
@api.constrains('instructor_id', 'attendee_ids')
def _check_instructor_not_in_attendees(self):
for r in self:
~~~
`openacademy/views/openacademy.xml`
~~~
</field>
</record>
<!-- calendar view -->
<record model="ir.ui.view" id="session_calendar_view">
<field name="name">session.calendar</field>
<field name="model">openacademy.session</field>
<field name="arch" type="xml">
<calendar string="Session Calendar" date_start="start_date"
date_stop="end_date"
color="instructor_id">
<field name="name"/>
</calendar>
</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,calendar</field>
</record>
<menuitem id="session_menu" name="Sessions"
~~~
##### 搜索視圖
搜索視圖的`<field>`元素可以使用`@filter_domain`覆蓋為在給定字段上搜索而生成的域。在給定的域中,`self`表示用戶輸入的值。在下面的示例中,它用于搜索兩個字段`name`和`description`。搜索視圖還可以包含`<filter>`元素,這些元素用作預定義搜索的切換。過濾器必須具有以下屬性之一:
`domain`
給搜索指定domain表達式
`context`
給搜索指定上下文;使用`group_by`對結果進行分組。
~~~
<search string="Ideas">
<field name="name"/>
<field name="description" string="Name and description"
filter_domain="['|', ('name', 'ilike', self), ('description', 'ilike', self)]"/>
<field name="inventor_id"/>
<field name="country_id" widget="selection"/>
<filter name="my_ideas" string="My Ideas"
domain="[('inventor_id', '=', uid)]"/>
<group string="Group By">
<filter name="group_by_inventor" string="Inventor"
context="{'group_by': 'inventor_id'}"/>
</group>
</search>
~~~
對于非默認的搜索視圖,使用`search_view_id`字段。而通過`context`字段為搜索字段設置默認值:`search_default_field_name`表單的上下文關鍵字將初始化field_name的值。搜索過濾器必須有`@name`選項,并且其值是布爾類型的(只能在默認情況可用)
> 練習搜索視圖
>
> * 在課程搜索視圖中添加按鈕,用以篩選當前用戶負責的課程,并且作為默認選擇。
> * 再添加一個分組按鈕,用于對當前用戶負責的課程進行分組。
`openacademy/views/openacademy.xml`
~~~
<search>
<field name="name"/>
<field name="description"/>
<filter name="my_courses" string="My Courses"
domain="[('responsible_id', '=', uid)]"/>
<group string="Group By">
<filter name="by_responsible" string="Responsible"
context="{'group_by': 'responsible_id'}"/>
</group>
</search>
</field>
</record>
~~~
~~~
<field name="res_model">openacademy.course</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context" eval="{'search_default_my_courses': 1}"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create the first course
</p>
~~~
##### 甘特圖
水平條狀的甘特圖通常用于顯示項目計劃和進度,根元素是`<gantt>`。
~~~
<gantt string="Ideas"
date_start="invent_date"
date_stop="date_finished"
progress="progress"
default_group_by="inventor_id" />
~~~
> 練習甘特圖
> 添加甘特圖使用戶可以查看授課的日程排期,授課將按講師分組。
>
> * 創建一個計算字段,表示以小時計算的授課持續時間
> * 添加甘特圖,并且將甘特圖添加到授課模型的action上。
`openacademy/models.py`
~~~
end_date = fields.Date(string="End Date", store=True,
compute='_get_end_date', inverse='_set_end_date')
hours = fields.Float(string="Duration in hours",
compute='_get_hours', inverse='_set_hours')
@api.depends('seats', 'attendee_ids')
def _taken_seats(self):
for r in self:
~~~
~~~
end_date = fields.Datetime.from_string(r.end_date)
r.duration = (end_date - start_date).days + 1
@api.depends('duration')
def _get_hours(self):
for r in self:
r.hours = r.duration * 24
def _set_hours(self):
for r in self:
r.duration = r.hours / 24
@api.constrains('instructor_id', 'attendee_ids')
def _check_instructor_not_in_attendees(self):
for r in self:
~~~
`openacademy/views/openacademy.xml`
~~~
</field>
</record>
<record model="ir.ui.view" id="session_gantt_view">
<field name="name">session.gantt</field>
<field name="model">openacademy.session</field>
<field name="arch" type="xml">
<gantt string="Session Gantt" color="course_id"
date_start="start_date" date_delay="hours"
default_group_by='instructor_id'>
<field name="name"/>
</gantt>
</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,calendar,gantt</field>
</record>
<menuitem id="session_menu" name="Sessions"
~~~
##### 圖形視圖
圖形視圖用來表示對模型的概述和分析,根元素是`<graph>`。
> 注意
> 多維表的核心視圖(根元素`<pivot>`)允許選擇文件管理器以獲得正確的圖形數據庫,然后再轉到更多的圖形視圖。核心視圖與圖形視圖共享相同的內容定義。
聚合視圖有4種顯示模式,通過`@type`屬性定義。
**Bar(默認值)**
條形圖,第一個維度用于在水平軸上定義組,其它維度定義每個組的聚合條。默認情況下,條是并排的,也可以通過`<graph>`的`@stacked="True"`來讓條堆疊。
**Line**
2維折線圖
**Pie**
2維餅圖
圖形視圖包含的`<field>`元素有`@type`屬性定義值:
`row(默認值)`
該字段是聚合的
`measure`
該字段是分組后聚合的
~~~
<graph string="Total idea score by Inventor">
<field name="inventor_id"/>
<field name="score" type="measure"/>
</graph>
~~~
> 警告
> 圖形視圖只能對數據庫字段進行聚合,不能對不存儲在數據庫的計算字段進行聚合。
>
> 練習圖形視圖
> 在授課對象中添加圖形視圖,為每個課程在條形視圖下顯示出席人數。
>
> * 添加字段將出席人數這計算字段存儲在數據庫
> * 添加相關圖形視圖
`openacademy/models.py`
~~~
hours = fields.Float(string="Duration in hours",
compute='_get_hours', inverse='_set_hours')
attendees_count = fields.Integer(
string="Attendees count", compute='_get_attendees_count', store=True)
@api.depends('seats', 'attendee_ids')
def _taken_seats(self):
for r in self:
~~~
~~~
for r in self:
r.duration = r.hours / 24
@api.depends('attendee_ids')
def _get_attendees_count(self):
for r in self:
r.attendees_count = len(r.attendee_ids)
@api.constrains('instructor_id', 'attendee_ids')
def _check_instructor_not_in_attendees(self):
for r in self:
~~~
`openacademy/views/openacademy.xml`
~~~
</field>
</record>
<record model="ir.ui.view" id="openacademy_session_graph_view">
<field name="name">openacademy.session.graph</field>
<field name="model">openacademy.session</field>
<field name="arch" type="xml">
<graph string="Participations by Courses">
<field name="course_id"/>
<field name="attendees_count" type="measure"/>
</graph>
</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,calendar,gantt,graph</field>
</record>
<menuitem id="session_menu" name="Sessions"
~~~
##### 看板視圖
看板視圖用于任務組織、生產進度等,根元素是`<kanban>`。看板視圖顯示一組可按列分組的卡片。每個卡片表示一個記錄,每列都顯示聚合字段的值。例如項目任務可以按階段(每列是一個階段)分組或者按負責人(每列是一個用戶)分組。看板視圖將每個卡的結構定義為表單元素(包括基本HTML)和QWeb的混合。
> 練習看板視圖
> 添加顯示按課程分組的授課看板視圖(列是課程)
>
> * 授課模型中添加整型字段`color`
> * 添加看板視圖并更新action
`openacademy/models.py`
~~~
duration = fields.Float(digits=(6, 2), help="Duration in days")
seats = fields.Integer(string="Number of seats")
active = fields.Boolean(default=True)
color = fields.Integer()
instructor_id = fields.Many2one('res.partner', string="Instructor",
domain=['|', ('instructor', '=', True),
~~~
`openacademy/views/openacademy.xml`
~~~
</record>
<record model="ir.ui.view" id="view_openacad_session_kanban">
<field name="name">openacad.session.kanban</field>
<field name="model">openacademy.session</field>
<field name="arch" type="xml">
<kanban default_group_by="course_id">
<field name="color"/>
<templates>
<t t-name="kanban-box">
<div
t-attf-class="oe_kanban_color_{{kanban_getcolor(record.color.raw_value)}}
oe_kanban_global_click_edit oe_semantic_html_override
oe_kanban_card {{record.group_fancy==1 ? 'oe_kanban_card_fancy' : ''}}">
<div class="oe_dropdown_kanban">
<!-- dropdown menu -->
<div class="oe_dropdown_toggle">
<i class="fa fa-bars fa-lg"/>
<ul class="oe_dropdown_menu">
<li>
<a type="delete">Delete</a>
</li>
<li>
<ul class="oe_kanban_colorpicker"
data-field="color"/>
</li>
</ul>
</div>
<div class="oe_clear"></div>
</div>
<div t-attf-class="oe_kanban_content">
<!-- title -->
Session name:
<field name="name"/>
<br/>
Start date:
<field name="start_date"/>
<br/>
duration:
<field name="duration"/>
</div>
</div>
</t>
</templates>
</kanban>
</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,calendar,gantt,graph,kanban</field>
</record>
<menuitem id="session_menu" name="Sessions"
parent="openacademy_menu"
~~~
作者:luohuayong
鏈接:http://www.jianshu.com/p/511f32b28a13
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
- 開發教程
- Odoo10開發教程一(構建模塊)
- Odoo10開發教程二(基本視圖)
- Odoo10開發教程三(模型關聯)
- Odoo10開發教程四(繼承)
- Odoo10開發教程五(計算字段和默認值)
- Odoo10開發教程六(高級視圖)
- Odoo10開發教程七(工作流和安全)
- 參考手冊
- odoo V10中文參考手冊(一:ORM API)
- odoo V10中文參考手冊(指導規范)
- 技巧
- odoo 常用widget
- Odoo(OpenERP)開發實踐:菜單隱藏(1)
- Odoo(OpenERP)開發實踐:菜單隱藏(2)
- Odoo(OpenERP)開發實踐:數據模型學習
- Odoo中自動備份數據庫
- Odoo(OpenERP)應用實踐: 使用db-filter參數實現通過域名指定訪問哪個數據庫
- Odoo(OpenERP)配置文件openerp-server.conf詳解
- Odoo(OpenERP v8)數據模型(Data Model)
- odoo10學習筆記十七:controller
- Qweb定義