Odoo 12开发之看板视图和用户端 QWeb
前言:
Qweb是odoo使用的模板引擎,基于xml来生成HTML片段和页面.
通过Qweb可生成丰富的看板视图,报表和cmx
一·了解看板
# 两种布局
# 1. 卡片列表
# 2. 组织成不同的卡片
二·设计看板视图
优先级、看板状态和颜色
# 看版中其他字段:
priority # 让用户组织他们的工作项,标记什么应优先处理
kanban_state # 标记是否应移向下一阶段或因某种原因原地不动。在模型定义层中两者都是选择项字段。在视图层,对它们有特别的组件用于表单和看板视图。
color # 用于存储看板卡片显示的颜色,并可通过看板视图中的颜色拾取器菜单设置
# 如下例:
class Checkout(models.Model):
...
priority = fields.Selection(
[('0', 'Low'),
('1', 'Normal'),
('2', 'High')],
'Priority',
default='1')
kanban_state = fields.Selection(
[('normal', 'In Progress'),
('blocked', 'Blocked'),
('done', 'Ready for next stage')],
'Kanban State',
default='normal')
看板卡片元素
# 看板视图框架包含了一个<kanban>外层元素和一下基础结构
# 看板支持属性:
default_group_by # 设置默认列分组使用的字段
default_order # 设置看板项默认使用的排序
quick_create=”false” # 禁用了每列顶部的快速创建选项(大的加号符号),快速创建只需提供标题描述即可创建新项。false是 JavaScript 的语法,必须是小写字母。
class # 为渲染看板视图的根元素添加 CSS 类。相关类是_kanban_small_column,让列比默认的更加紧湊。其它类可由我们模块的 CSS 文件来进行提供。
group_create, group_edit, group_delete和quick_create_view # 可设置为 false 来禁用看板列上对应的操作。如group_create=”false”删除右侧添加新列的按钮。
on_create # 用于创建用户点击左上角 Create 按钮时弹出的自定义简单表单视图窗口。应为相应的表单视图添加<module>.<xml_id>值。
### <progressbar> 如下属性:
field # 是对列中各项进行颜色分组的字段名
colors # 是一个字典,将分组字段值与以下三种颜色分别进行映射:danger (红色), warning (黄色)或success (绿色)。
sum_field # 是一个可选项,用于选取整列汇总的字段名。如未设置,会使用各项的计数值。
<kanban default_group_by="stage_id" class="o_kanban_small_column">
<!-- Fields -->
<field name="stage_id" />
<field name="id" />
<field name="color" />
<field name="kanban_state" />
<field name="priority" />
<field name="message_partner_ids" />
<!-- Optional progress bar -->
<progressbar
field="kanban_state"
colors='{"done": "success", "blocked": "danger"}' />
<!-- Templates with HTML snippets to use -->
<templates>
<t t-name="kanban-box">
<!-- HTML Qweb template -->
</t>
</template>
</kanban>
三·Qweb模板语言
# QWeb 会查找模板种的特殊指令,并动态的替换掉生成的HTML.
# 对于使用带有QWeb指令的(t-if t-foreach)的特殊元素.该元祖不会在最终产生的xml/html有任何输出
# QWeb指令常使用运算的表达式生成不同结果:
# 报表和网页使用服务端QWeb的python实现
# 看板使用客户端js实现,即看板视图种的QWeb表达式应使用js编写
### 看板视图 , 内部的步骤流程
# 1. 获取模板的XML进行渲染
# 2. 调用服务端read()方法来获取模板中所涉及的字段数据
# 3. 定位kanban-boxs模板并使用QWeb解析它来输出最终的HTML片断
# 4. 在浏览器显示(DOM)中注入 HTML
QWeb JavaScript 运行上下文
# QWeb指令使用表达式的运行来生成结果
raw_value # 是由服务端read()方法返回的值
value # 根据用户设置来格式化
widget # 是当前KanbanRecord()组件对象的引用,用于在看板种渲染当前记录
record # 是 widget.record的简写形式,使用点号标记来提供对可用字段的访问
read_only_mode # 标识当前视图是否为读模式(非编辑模式)是widget.view.options.read_only_mode的简写形式。
instance # 是对全部网页客户端实例的一个引用
### XML 标准中,这些字符具有特殊含义
lt是小于
lte是小于等于
gt是大于
gte是大于等于
字符串替换动态属性– t-attf
# t-attf 来作为顶级<div>元素设置一个类,根据卡片的color字段值来显示颜色
# t-attf 指令查找代码块运行并替换结果,通过{{}} 和#{{}} 来进行分隔. 代码块的内容是任意js表达式,QWeb表达式中的任意可用变量.
# 例子:
t-attf-class="oe_kanban_text_red" # 显示为红色
t-attf-class="oe_kanban_text_{{
record.priority.raw_value lt '2'
? 'black' : 'red'}}" # 记录的星星小于2是黑色,否则是红色
<li t-attf-class="oe_kanban_text_{{
record.priority.raw_value lt '2'
? 'black' : 'red'}}">
<field name="user_id" />
</li>
表达式动态属性 t–att–
# t-att- 是QWeb指令通过表达式动态生成的属性值.
# .value字段返回在屏幕上显示的值,鼠标悬停在图像上时就会显示相对于的用户名.
t-att-title="record.member_id.value"
循环 – t-foreach
# t-foreach 指令接受一个js表达式.
t-as 指令设置别名,
### rec 变量
rec_index是迭代索引,从0开始
rec_size是集合中的元素数量
rec_first在迭代的第一个元素中为真
rec_last在迭代的最后一个元素中为真
rec_even在索引为偶数时为真
rec_odd在索引为奇数时为真
rec_parity根据当前索引为odd或even
rec_all表示进行迭代的对象
rec_value在迭代{key:value} 字典时,存储value (rec存储键名)
### t-foreach="record.message_partner_ids.raw_value.slice(0, 3)"
是对取到内容进行了切片
<t t-foreach="record.message_partner_ids.raw_value.slice(0,3)" t-as="rec">
<img t-att-src="kanban_image('res.partner', 'image_small', rec)"
class="oe_avatar" width="24" height="24" alt="" />
</t>
条件判断 – t-if
<t t-if="record.num_books.raw_value == 0">
<li>No books.</li>
</t>
<t t-elif="record.num_books.raw_value gt 9">
<li>A lot of books!</li>
</t>
<t t-else="">
<li><field name="num_books" /> books.</li>
</t>
渲染值 t-esc和t-raw
### <field/>元素可以渲染值 t-esc 也可以渲染值, t-raw是确定数据是否安全的渲染值(避免使用)
# t-esc 指令运行表达式并将其渲染为转义后的 HTML 值
<t t-esc="record.message_partner_ids.raw_value" />
# t-raw 确定源数据是安全的,可以无需转义使用t-raw 来渲染原始值
<t t-raw="record.message_partner_ids.raw_value" />
为变量设置值 – t-set
# 对于更复杂的逻辑,可以将表达式结果存储在变量中
# t-set指令来实现,设置变量名
# t-value指令来添加表达式计算分配的值
<t t-set="red_or_black"
t-value="record.priority.raw_value gte '2' ? 'oe_kanban_text_red' :''" />
<li t-att-class="red_or_black">
<field name="user_id" />
</li>
调用和复用其它模板 – t-call
# 重复调用 , 一句 t-name设置的名字.可重复调用
<t t-name="follower_avatars">
<div>
<t t-foreach="record.message_partner_ids.raw_value.slice(0,3)"
t-as="rec">
<img t-att-src="kanban_image('res.partner', 'image_small', rec)"
class="oe_avatar" width="24" height="24" alt="" />
</t>
</div>
</t>
### 重复调用
<t t-call="follower_avatars" />
### 更优雅的方式实现 调用模板传递参数
# slice(0,arg_max)
<t t-name="follower_avatars">
<div>
<t t-foreach="record.message_partner_ids.raw_value.slice(0, arg_max)"
t-as="rec">
<img t-att-src="kanban_image('res.partner', 'image_small', rec)"
class="oe_avatar" width="24" height="24" alt="" />
</t>
</div>
</t>
### 子模板调用时定义arg_max变量
<t t-call="follower_avatars">
<t t-set="arg_max" t-value="3" />
</t>
字典和列表动态属性
### 映射
# 定义:<p t-att="{'class': 'oe_bold', 'name': 'Hello'}" />
# 输出:<p class="oe_bold" name="Hello" />
### pair
# 定义:<p t-att="['class', 'oe_bold']" />
# 输出:<p class="oe_bold" />
四·看板视图的继承
# 与普通视图的继承一样
# XPath 查找<t t-name=”kanban-box”>元素内的<field name=”display_name”>
<record id="res_partner_kanban_inherit" model="ir.ui.view">
<field name="name">Contact Kanban modification</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view" />
<field name="arch" type="xml">
<xpath expr="//t[@t-name='kanban-box']//field[@name='display_name']"
position="before">
<span>Name:</span>
</xpath>
</field>
</record>
五·自定义 CSS 和 JavaScript
# 自定义css和js文件
# 步骤
# 1. 在views目录下新建checkout_kanban_assets.xml数据文件加载样式
# 2. 在static/src/css编写css src/js编写js
# 3. 将数据文件加载到__manifest__.py的data种
# library_checkout/views/checkout_kanban_assets.xml:
<odoo>
<template id="assets_backend" inherit_id="web.assets_backend"
name="Library Checkout Kanban Assets">
<xpath expr="." position="inside">
<link rel="stylesheet"
href="/library_checkout/static/src/css/checkout_kanban.css" />
<script type="text/javascript"
src="/library_checkout/static/src/js/checkout_kanban.js">
</script>
</xpath>
</template>
</odoo>