描述:QWeb是Odoo2使用的主要模板引擎。它是一个XML模板引擎,主要用于生成HTML片段和页面。模板指令被指定为带有t-前缀的XML属性,例如,条件为t-if,元素和其他属性被直接呈现。
避免元素渲染,一个占位符元素也是可用的,它执行它的指令,但它本身不产生任何输出:
<t t-if="condition">
<p>Test</p>
</t>
1.数据输出
QWeb有一个主输出指令,它在显示用户提供的内容时自动对内容进行html转义,以限制XSS风险:esc
。esc 接受一个表达式,对它求值并打印内容:
<p><t t-esc="1"/></p>
结果:
<p>1</p>
2. 条件句
QWeb有一个条件指令if
,它计算作为属性值给出的表达式:类似vue中的v-if
<div>
<t t-if="条件">
<p>ok</p>
</t>
</div>
如果条件成立:
<div>
<p>ok</p>
</div>
如果条件不成立:
<div>
</div>
也可以直接在标签中这样写,不用加< t>标签
<div>
<p t-if="condition">ok</p>
</div>
也可以用 if else 进行嵌套,如下:哪个标签表达式成立,哪个结果显示
<div>
<p t-if="user.birthday == today()">Happy birthday!</p>
<p t-elif="user.login == 'root'">Welcome master!</p>
<p t-else="">Welcome!</p>
</div>
3.循环迭代
QWeb有一个foreach
迭代指令,它接受一个返回要迭代的集合的表达式,还有第二个参数t-as
,它提供了用于迭代的“current item”的名称
<t t-foreach="[1, 2, 3]" t-as="i">
<p><t t-esc="i"/></p>
</t>
结果:
<p>1</p>
<p>2</p>
<p>3</p>
等价于前面的例子
<p t-foreach="[1, 2, 3]" t-as="i">
<t t-esc="i"/>
</p>
4.属性
QWeb可以动态计算属性,并在输出节点上设置计算结果。这是通过t-att(属性)
指令来实现的,它以3种不同的形式存在:
t-att-$name
:创建一个名为 $name 的属性,对属性值进行评估,并将结果设置为属性值
<div t-att-a="42"/>
结果:
<div a="42"></div>
t-attf-$name
:与前面一样,但参数是一个格式字符串,而不仅仅是一个表达式,通常用于混合文字字符串和非文字字符串:
<t t-foreach="[1, 2, 3]" t-as="item">
<li t-attf-class="row {{ (item_index % 2 === 0) ? 'even' : 'odd' }}">
<t t-esc="item"/>
</li>
</t>
结果:
<li class="row even">1</li>
<li class="row odd">2</li>
<li class="row even">3</li>
3.t-att=mapping
如果参数是映射,则每个(键、值)对生成一个新的属性及其值
<div t-att="{'a': 1, 'b': 2}"/>
结果:
<div a="1" b="2"></div>
4.t-att=pair
如果参数是一对(元组或2个元素的数组),那么pair中的第一项是属性的名称,第二项是值
<div t-att="['a', 'b']"/>
结果:
<div a="b"></div>
5.设置变量
QWeb允许从模板中创建变量,记忆计算(多次使用),给数据块起一个更清晰的名字
这是通过set指令完成的,它接受要创建的变量的名称。要设置的值可以通过两种方式提供
- 一个包含表达式的
t-value
属性,将设置其计算结果
<t t-set="foo" t-value="2 + 1"/>
<t t-esc="foo"/>
将会输出 3
- 如果没有
t-value
属性,则呈现节点的主体,并将其设置为变量的值
<t t-set="foo">
<li>ok</li>
</t>
<t t-esc="foo"/>
结果
<li>ok</li>
6.calling sub-templates 替代模板
QWeb模板可以用于顶级渲染,但也可以使用t-call
指令从另一个模板中使用它们(以避免重复或给模板的各个部分命名)
<t t-call="other-template"/>
如果other_template
被定义为,它将使用父模板的执行上下文调用命名模板
<p><t t-value="var"/></p>
他调用上面将被渲染为(无内容),但是
<t t-set="var" t-value="1"/>
<t t-call="other-template"/>
结果<p>1</p>
然而,这有一个问题,即从t-call
外部可见。或者,在call
指令体中设置的内容将在调用子模板之前进行评估,并且可以改变局部上下文
<t t-call="other-template">
<t t-set="var" t-value="1"/>
</t>
call
指令的主体可以是任意复杂的(不仅仅是set
指令),它的呈现形式将作为一个神奇的0变量在被调用模板中可用
<div>
This template was called with content:
<t t-raw="0"/>
</div>
因此被称为
<t t-call="other-template">
<em>content</em>
</t>
结果:
<div>
This template was called with content:
<em>content</em>
</div>
7.Python
a.独家指令
资源包
`t-field`指令只能在“智能”记录(browse方法的结果)上执行字段访问(a.b)时使用。它能够根据字段类型自动格式化,并集成在网站的富文本版本中。
`t-options` 可用于自定义字段,最常见的选项是widget,其他选项是字段或小部件相关的
b.调试以排除故障
t-debug 使用PDB的set_trace API调用调试器。参数应该是模块的名称,在模块上调用set_trace方法
<t t-debug="pdb"/>
结果等价于importlib.import_module(“pdb”)
c.辅助
Request-based:大多数python端QWeb的使用都在控制器中(和HTTP请求期间),在这种情况下,存储在数据库中的模板(作为视图)可以通过调用odoo.http.HttpRequest.render()简单地呈现:
response = http.request.render('my-template', {
'context_value': 42
})
这将自动创建一个响应对象,该对象可以从控制器返回(或进一步定制以适应该对象)。
View-based:比上一个助手层次更深的是ir.ui.view
上的render
方法:render(cr, uid, id[, values][, engine='ir.qweb][, context])
通过数据库id或外部id呈现QWeb视图/模板。模板自动从ir.ui加载记录
8.Javascript
定义模板
t-name
指令只能放在模板文件的顶层(直接指向文档根目录的子目录):
<templates>
<t t-name="template-name">
<!-- template code -->
</t>
</templates>
它不接受其他参数,但可以与< t>元素或任何其他元素一起使用。对于< t>元素,< t>应该有一个子元素。
模板名是一个任意的字符串,但是当多个模板相关时(例如称为子模板),习惯上使用点分隔的名称来表示层次关系
模板继承:
模板可以用来修改继承模板中的内容
可以由其他模块创建:如从给定的父模板创建一个新模板
模板继承是通过使用两个指令来执行的:
1.t-inherit
要继承的模板的名称是哪个
2.t-inherit-mode
这是继承的行为:它既可以设置为primary
以从父模板创建新的子模板,也可以设置为扩展以在适当的位置更改父模板
主继承(子模板)
<t t-name="child.template" t-inherit="base.template" t-inherit-mode="primary">
<xpath expr="//ul" position="inside">
<li>new element</li>
</xpath>
</t>
扩展继承(就地转换)
<t t-inherit="base.template" t-inherit-mode="extension">
<xpath expr="//tr[1]" position="after">
<tr><td>new cell</td></tr>
</xpath>
</t>