QWeb 是基于xml 生成html 的模板引擎
先上代码例子:
todo_task.py 
----------------------------- 
# -*- coding: utf-8 -*-

from openerp import models, fields


class TodoTask(models.Model):
_inherit = 'todo.task'
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')
----------------------------------

todo_view.xml
----------------------------------
<?xml version="1.0"?>
<openerp>
<data>
<!-- Add Kanban view mode to the menu Action: -->
<act_window id="todo_app.action_todo_task"
name=" To-Do Tasks"
res_model="todo.task"
view_mode="kanban,tree,form,calendar,gantt,graph"
context="{'search_default_filter_my_tasks': True}"/>
<!-- Add Kanban view -->
<record id="To-do Task Kanban" model="ir.ui.view">
<field name="name">To-do Task Kanban</field>
<field name="model">todo.task</field>
<field name="arch" type="xml">
<!-- Empty for now, but the Kanban will go here! -->
<kanban>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_vignette">
<img t-att-src="kanban_image('res.partner','image_medium', record.id.value)"
class="oe_kanban_image"/>
<div class="oe_kanban_details">
<!-- Title and Data content -->
<h4>
<a type="open">
<field name="name"/>
</a>
</h4>
<field name="tags"/>
<ul>
<li>
<field name="user_id"/>
</li>
<li>
<field name="date_deadline"/>
</li>
</ul>
<field name="kanban_state" widget="kanban_state_selection"/>
<field name="priority" widget="priority"/>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</data>
</openerp>

----------------------------------

# 看板视图的风格
Vignette 就是左边有一个小插件,在系统中常用于 客户、产品、等
Card 常用于 CRM中的机会和商机,也用在项目任务

# 看板视图
<kanban> 顶级元素
常用两个字段 priority , kanban_state
priority 显示项目的紧急程度
kanban_state 显示项目的各阶段
<templates> 主要有一个命名 kanban-box 采用下面的元素 <t t-name="kanban-box">...</t>
<field>这是字段,若是只是用于表达,就放在<templates>之前,字段具有聚合性如:
<field name="effort_estimated" sum="Total Effort" />
<kanban> 顶级元素支持一些属性
default_group_by 默认分组条件
default_order 默认排序条件
quick_create="false" 不能快速创建选项
class 加入css类
css类,有两个主要的 oe_kanban_vignette 和 oe_kanban_details
<img>中的 t-att-src 可以计算图片的src存在数据库中的值

# 在看板视图中的动作
在<a>中有 type 属性 像 <button>里面的功能似的
type的值有:
open: 打开表单视图
edit: 打开并编辑表单视图
delete: 删除记录

#卡片风格的看板视图
示例代码:
<t t-name="kanban-box">
<div class="oe_kanban_card">
<div class="oe_dropdown_kanban oe_dropdown_toggle">
<!-- Top-right drop down menu -->
</div>
<div class="oe_kanban_content">
<!-- Option menu will go here! -->

<h4>
<a type="open">
<field name="name"/>
</a>
</h4>
<field name="tags"/>
<ul>
<li>
<field name="user_id"/>
</li>
<li>
<field name="date_deadline"/>
</li>
</ul>
<div class="oe_kanban_bottom_right">
<field name="kanban_state"
widget="kanban_state_selection"/>
</div>
<div class="oe_kanban_footer_left">
<field name="priority" widget="priority"/>
</div>
</div>
</div>
</t>

* 给QWeb加动态内容

#条件表达式
<t t-if="record.effort_estimate.raw_value > 0">
<li>Estimate <field name="effort_estimate"/></li>
</t>

比较符号:
lt(<) lte(<=) gt(>) gte(>=)
注 < <= 不能用在表达式中,只能用字母代替

# 输出值 t-esc 和 t-raw
<t t-esc="record.message_follower_ids.raw_value" />
<t t-raw="record.message_follower_ids.raw_value" />
t-esc 过滤安全值,像html元素
t-raw 数据库中的原始数据

# 循环
<t t-foreach="record.message_follower_ids.raw_value" t-as="rec">
<t t-esc="rec" />;
</t>
t-foreach="record.message_follower_ids.raw_value.slice(0, 3)" 还可以切片
还有一些变量
rec_index 从0开始循环索引
rec_size 要循环的记录集大小
rec_first 第一个元素
rec_last 最后一个元素
rec_even index为偶数时为真
rec_odd index为奇数时为真
rec_parity 是偶数和奇数
rec_all 表示循环结束的标识
rec_value 循环一个字典时,的键的值

# 动态属性
<div>
<t t-foreach="record.message_follower_ids.raw_value.slice(0, 3)"
t-as="rec">
<img t-att-src="kanban_image(
'res.partner', 'image_small', rec)"
class="oe_kanban_image oe_kanban_avatar_smallbox"/>
</t>
</div
t-att- prefixed 如 <img>的src 就可以 t-att-src="..."

# 属性的字符替换
<span t-attf-class="oe_kanban_text{{
record.date_deadline.raw_value and
!(record.date_deadline.raw_value > (new Date()))
? '_red' : '_black' }}">
<field name="date_deadline"/>
</span>
t-attf-prefixed 取代内容,上面的就是动态类

# 变量设置
<t t-set="red_or_black" t-value="
record.date_deadline.raw_value and
record.date_deadline.raw_value lte (new Date())
? 'oe_kanban_text_red' : ''" />
<span t-att-class="red_or_black">
<field name="date_deadline" />
</span>
t-set 设置变量 t-value设置变量的值
还可以这样用
<t t-set="calendar_sign">
<span class="oe_e">&#128197;</span>
</t>
<t t-raw="calendar_sign" />

# 包含其它模板
<t t-name="follower_avatars">
<div>
<t t-foreach="record.message_follower_ids.raw_value.slice(0, 3)"
t-as="rec">
<img t-att-src="kanban_image(
'res.partner', 'image_small', rec)"
class="oe_kanban_image oe_kanban_avatar_smallbox"/>
</t>
</div>
</t>
。。。
<t t-call='follower_avatars' />

t-call 调用其它模板

复用灵活一些
<t t-name="follower_avatars">
<div>
<t t-foreach="record.message_follower_ids.raw_value.slice(0, arg_max)"
t-as="rec">
<img t-att-src="kanban_image(
'res.partner', 'image_small', rec)"
class="oe_kanban_image oe_kanban_avatar_smallbox"/>
</t>
</div>
</t>
。。。
<t t-call='follower_avatars'>
<t t-set="arg_max" t-value='3' />

<t/>

# QWeb 其它指令

<p t-att="{'class': 'oe_bold', 'name': 'test1'}" />
结果显示
<p class="oe_bold" name="test1" />
t-att 接受字典
<p t-att="['class','oe_bold']"
结果显示
<p class="oe_bold">

# card类式加菜单
<div class="oe_dropdown_kanban oe_dropdown_toggle">
<span class="oe_e">í</span>
<ul class="oe_dropdown_menu">
<t t-if="widget.view.is_action_enabled('edit')">
<li>
<a type="edit">Edit...</a>
</li>
</t>
<t t-if="widget.view.is_action_enabled('delete')">
<li>
<a type="delete">Delete</a>
</li>
</t>
<!-- Color picker option: -->
<li>
<ul class="oe_kanban_colorpicker"
data-field="color"/>
</li>
</ul>
</div>

# card类式加颜色 
<field name="color" />
<div class="oe_kanban_card">
<div t-attf-class="oe_kanban_card
#{kanban_color(record.color.raw_value)}">

# 为长文本加省略号
<t t-esc="kanban_text_ellipsis(record.name.value, 32)" />
过超32个字符就加... 不显示内容了


# 自定义css 和javascript的资源

<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="assets_backend"
inherit_id="web.assets_backend"
name="Todo Kanban Assets">
<xpath expr="." position="inside">
<link rel="stylesheet"
href="/todo_kanban/static/src/css/todo_kanban.css"
/>
<script type="text/javascript"
src="/todo_kanban/static/src/js/todo_kanban.js">
</script>
</xpath>
</template>
</data>
</openerp>

* 创建业务报表
上面学的QWeb技术有些可以用在报表上
先上点菜
todo_kanban/__openerp__.py
---------------
'data': ['todo_view.xml', 'todo_report.xml']
---------------

todo_report.xml
---------------
<?xml version="1.0"?>
<openerp>
<data>
<report id="report_todo_task_action"
string="To-do Tasks"
model="todo.task"
report_type="qweb-pdf"
name="todo_kanban.report_todo_task_template"
/>
<template id="report_todo_task_template">
<t t-call="report.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="report.external_layout">
<div class="page">
<!-- Report page content -->
</div>
</t>
</t>
</t>
</template>
</data>
</openerp>

<report> 是 ir.actions.report.xml 模型的快捷方式
报表可以在 设置->技术->报表 可以查到
t-call 调用的标准报告架构,这个很重要
report.external_layout 包含头部和尾部 ,也可以只用 report.internal_layout 只用
基础架构的头部,其它部分自己写


#注意,报表,用到了wkhtmltopdf依赖
http://wkhtmltopdf.org/downloads.html wkhtmltopdf-0.12.1 版本
$ sudo apt-get remove --purge wkhtmltopdf
$ cd /tmp
$ wget http://downloads.sourceforge.net/project/wkhtmltopdf/archive/0.12.1/
wkhtmltox-0.12.1_linux-trusty-adm64.deb

$ sudo dpkg -i wkhtmltox-0.12.1_linux-trusty-amd64.deb


#在报表中呈现数据

可用的变量:
docs 循环打印出一个记录集
doc_ids 一个记录集的ids列表打印出来
doc_model 调用哪个模型来处理
time 时间
user 本次执行报告的用户
res_company 当前用户所在的公司

字段值用 t-field 属性 还可以用其补充属性 t-field-options
上一道菜:
<h2 t-field="o.name"/>
<p t-field="o.user_id.name"/>
<ul>
<t t-foreach="o.message_follower_ids" t-as="f">
<li>
<img t-if="f.image_small"
t-att-src="'data:image/png;base64,%s' % f.image_small"
style="max-height: 45px;"/>
<span t-field="f.name"/>
</li>
</t>
</ul>
有货币字段:
<span t-field="o.amount"
t-field-options='{
"widget": "monetary",
"display_currency": "o.pricelist_id.currency_id"}'/>

<div t-field="res_company.partner_id"
t-field-options='{
"widget": "contact",
"fields": ["address", "name", "phone", "fax"],
"no_marker": true}' />

支持语言翻译
<template id="report_todo_task_template">
<t t-call="report.html_container">
<t t-foreach="doc_ids" t-as="doc_id">
<t t-raw="translate_doc(doc_id, doc_model,
'user_id.partner_id.lang',
'todo_kanban.report_todo_task_doc')"/>
</t>
</t>
</template>
translate_doc

#设计报表内容
上菜
<template id="report_todo_task_doc">
<t t-call="report.external_layout">
<div class="page">
<div class="row">
<div class="col-xs-12">
<h2>
<span t-field="o.name"/>
</h2>
</div>
</div>
<div class="row">
<div class="col-xs-8">
By:
<span t-field="o.user_id"/>
</div>
<div class="col-xs-4">
Deadline:
<span t-field="o.date_deadline"/>
</div>
</div>
<!-- Table -->
<table class="table table-bordered">
<!-- Table header -->
<tr>
<th>Avatar</th>
<th>Name</th>
</tr>
<!-- Table rows -->
<t t-foreach="o.message_follower_ids" t-as="f">
<!-- Each row -->
<tr>
<td>
<img t-if="f.image_small"
t-att-src="'data:image/png;base64,%s' % f.image_small"
style="max-height: 32px;"/>
</td>
<td>
<span t-field="f.name"/>
</td>
</tr>
<!-- Totals in a last row -->
<t t-if="f_last">
<tr>
<td colspan="2">
<strong>
<p class="text-right">
<t t-esc="len(o.message_follower_ids)"/>
followers
</p>
</strong>
</td>
</tr>
</t>
<!-- End table totals -->
</t>
</table>
</div>
</t>
</template> 
注:col-xs-N N代表多少列 像bootstrap写法,一行划成12列
<t t-if="f_last"> 循环到了最后


#纸张格式

<record id="report_todo_task_action" model="ir.actions.report.xml">
<field name="name">To-do Tasks</field>
<field name="model">todo.task</field>
<field name="report_type">qweb-html</field>
<field name="template_name">
todo_kanban.report_todo_task_template
</field>
<field name="paper_format_id" ref="report.paperformat_euro"/>
</record>
paper_format_id 引用了 report.paperformat_euro 这个格式,这个值,可以在
设置->技术->报告->纸张格式