第四章 QWeb
首先我们需要知道QWeb是什么, QWeb是odoo用来渲染HTML的模板引擎, 类似于Jinjia2之于Django. QWeb引擎的标志就是使用t-开头的控制语句.下面我们来详细学习一下QWeb模板引擎的相关知识.
输出与控制
开始总是最简单,我们先认识一个最简单的QWeb模板:
<t t-if="condition">
<p>Test</p>
</t>
这个例子非常简单, 如果condition表达式的结果为True, 那么
Test
就会被渲染出来,否则什么也不会输出.数据输出
如果我们希望在某个元素中输出一个表达式的值, 那么可以使用t-esc表达式:
<p><t t-esc="value"/></p>
如果value的值是html并且希望保留原格式输出,那么可以使用t-raw替代
<t t-raw="address">
逻辑控制 t-if
如果我们希望在某个元素中判断一个表达式的值, 那么可以使用t-if表达式:
<t t-if="condition">
<p>Test</p>
</t>
循环遍历 t-foreach
QWeb也支持循环遍历:
<p t-foreach="[1, 2, 3]" t-as="i">
<t t-out="i"/>
</p>
<t t-foreach="[1, 2, 3]" t-as="i">
<p><t t-esc="i"/></p>
</t>
t-as 将每次迭代的值传给变量i,方便后续的调用。
这里有多个内置的变量(以i为例):
- i_all: 迭代的对象
- i_value: 迭代对象的值,一般情况下和i的值相同,但是当迭代字典时,i为key,i_value为字典的值
- i_index: 序列
- i_size: 迭代列表的长度
- i_first: 列表的第一个值
- i_last: 列表的最后一个值
- i_parity: 当前迭代的奇偶性
- i_even: 当前迭代是否为偶数
- i_odd: 当前迭代是否为奇数
字段输出 t-field
如果想要输出odoo中某个模型的字段值, 那么可以使用t-field表达式:
<td>
<span t-field="ml.product_id.display_name"/><br/>
<span t-field="ml.product_id.description_picking"/>
</td>
那么 t-esc与 t-field有何区别?
t-esc用于输出数据,其值为python表达式执行完的结果。t-field 只能用于字段的访问,且只对存储的字段有效。另外,t-field-options可用于格式化字段值。例如:
<t-field="o.date" t-field-options='{"widget":"date"'}'/>
赋值变量 t-set
如果想要在QWeb自定义变量, 则可以选择t-set:
<t t-set="existing_variable" t-value="False"/>
属性操作
qweb中也可以操作html中的元素的属性值。
t-att-$name
t-att-$name用于创建动态的属性名:
<div t-att-name="42">
将创建一个拥有name属性值为42的节点:
<div name="42">
输出图片
如果我们想要在QWeb中输出图片,可以使用image_data_uri方法:
<img t-att-src="image_data_uri(order.image)" t-if="order.image" style="width:80px"/>
image_data_uri输出的是base64字符串,如果想要链接的形式则可以使用/web/image连接来完成。
<img t-att-src="/web/image?id=8&&model='sale.order'↦field=image_1920" t-if="order.image" style="width:80px"/>
t-attf-$name
t-attf-$name与t-att-$name类似,区别在于t-attf-$name输出的是格式化的字符串:
<t t-foreach="[1, 2, 3]" t-as="item">
<li t-attf-class="row false ? 'even' : 'odd' ">
<t t-out="item"/>
</li>
</t>
输出:
<li class="row even">1</li>
<li class="row odd">2</li>
<li class="row even">3</li>
数据的格式化
货币格式化
对应货币的金额精度,可以使用format_currency方法来格式化货币的精度:
<td class = "pos-right-align">
<t-esc = "widget.format_currency (taxdetail.amount)" />
</ td>
浮点类型与货币类型的转换
如果我们的字段本身就是货币类型,那么不需要使用转换,即可显示成2,000$这种形式的数据。
而如果是整形或者浮点型,那么我们可以使用t-options将其转换成货币类型
<span t-field="doc.amount_undiscounted" t-options="{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}"/>
- widget: 使用moentary部件
- display_currency: 指定货币字段。
如果想要控制货币精度,则需要到货币设置里改变它的精度值。
如果想要在Qweb中使用货币类型但同时又不想显示货币符号,那么需要配合我们的基础模块来完成:
<span t-field="line.price_unit" t-options="{'symbol':False}"/>
使用symbol设置成False来去除货币符号。
浮点数精度控制
对于浮点数的精度控制,我们可以使用t-options来协助我们:
<span t-out="line.amount_tax" t-options='{"widget": "float", "precision": 2}'/>
继承
基础的QWeb继承与之前的xml的写法都不一样,首先不需要odoo标签的包裹,另外不同于普通的模板,基础模板的写法需要使用templates标签包裹。
例如,我们给Many2one的部件添加一个前缀12345,可以这么写:
<templates>
<t t-extend="FieldMany2One">
<t t-jquery=".o_field_many2one" t-operation="before">
<a>123456</a>
</t>
</t>
</templates>
t-extend用于扩展Qweb的内容,配合t-operation可以实现xml中position类似的效果,具体来说,t-operation有以下几种值可以选择:
- append: 节点的主体被附加在上下文节点的末尾(在上下文节点的最后一个子节点之后)
- prepend: 节点的主体被添加到上下文节点(在上下文节点的第一个子节点之前插入)
- before: 节点的主体被插入在上下文节点之前
- after: 节点的主体被插入在上下文节点之后
- inner: 节点的主体替换上下文节点的子节点
- replace: 该节点的主体用于替换上下文节点本身
t-jquery指令采用一个CSS selector。此选择器用于扩展模板以选择应用指定的t-operation的上下文节点。
如果使用t-extend,odoo会要求你必须写入一个t-jquery选择器,如果想要使用replace的本身节点话,就会冲突。此时,你应该选择放弃使用t-extend,而使用同名的t-name将原有的代码覆盖掉,就像python的后定义的方法会覆盖掉前面定义的方法一样。
另外,如果想要完全重写某个QWeb部件,那么可以不用上面提到的几种操作,直接简单粗暴的定义一个同名的QWeb部件即可,后加载的部件会覆盖掉之前定义的部件。
- Qweb的继承视图不能设置组权限,否则会引起异常
- 在Qweb中还有一类叫做Qweb Fields的伪字段类型, 称它为伪字段类型,是因为虽然它顶着fields的名字却不存储在数据库中,只是在Qweb中作为中转站使用.这类字段的作用是将记录中的某些字段,转化为HTML片段嵌入到Qweb报表中.关于这部分的内容, 我们等到第五部分时会详细探讨。
- OWL Qweb的继承与传统的QWeb继承语法不同,我们在QWeb介绍时会详细说明。