QWeb是被Odoo[2]使用的主要的模版引擎。它是一个XML模板引擎[1],主要用于生成HTML片段和页面。
模板指令指定的XML属性的前缀 t-
,例如t-if
为条件,与元素和其他属性被直接渲染。
为了避免元素渲染,占位符元素<t>也可用,它执行指令,但本身并不会产生任何输出:
<t t-if="condition">
<p>Test</p>
</t>
结果如下:
<p>Test</p>
如果condition
是 true:
<div t-if="condition">
<p>Test</p>
</div>
则结果如下:
<div>
<p>Test</p>
</div>
数据输出
QWeb有一个主要的输出指令,它自动转移HTML,当显示用户提供的内容esc时,其内容限制XSS风险。
esc
获取表达式,计算并打印内容:
<p><t t-esc="value"/></p>
用设置为42的值value来渲染:
<p>42</p>
还有一个输出指令raw,它的行为与esc相同,但HTML没有转义输出。它可以显示分别标记有用(例如功能)或已消毒的用户提供的标记。
条件
QWeb有一个条件指令if
, 它评估作为属性值的表达式:
<div>
<t t-if="condition">
<p>ok</p>
</t>
</div>
如果条件为true,则渲染元素:
<div>
<p>ok</p>
</div>
但如果条件为false,则从结果中删除:
<div>
</div>
条件呈现适用于指令的承载者,它不一定是<t>
:
<div>
<p t-if="condition">ok</p>
</div>
将给出与前面示例相同的结果
附加条件分支指令 t-elif
和t-else
也是可用的:
<div>
<p t-if="user.birthday == today()">Happy bithday!</p>
<p t-elif="user.login == 'root'">Welcome master!</p>
<p t-else="">Welcome!</p>
</div>
循环
QWeb有一个迭代指令foreach
,它获取返回集合迭代的表达式,第二参数t-as提供要使用的名称为“当前项”的迭代:
<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>
像条件, foreach
适用于包含指令属性的元素,且
<p t-foreach="[1, 2, 3]" t-as="i">
<t t-esc="i"/>
</p>
相当于前一个例子
foreach
可以迭代数组(当前项将是当前值)、映射(当前项将是当前键)或整数(相当于迭代这包含0而不包含提供证书区间的数组上)。
除了通过t-as传递名称,foreach
为其他数据点提供一些其他变量:
警告
$as
将被传递给t-as的名称替换
$as_all
正在迭代的对象
$as_value
当前迭代值,对于列表和整数与$as相同的,但是对于映射它提供了一个值($as
提供键)
$as_index
当前迭代索引(迭代的第一项有索引0)
$as_size
集合的大小,如果可用的话
$as_first
当前项目是否是迭代的第一个项(相当于$as_index == 0
)
$as_last
当前项目是否是迭代的最后一个(相当于 $as_index + 1 == $as_size
),要求迭代(如数组)大小是可用的
$as_parity
要么是"even"
要么是 "odd"
,当前迭代循环的奇偶性
$as_even
指示当前迭代在偶数索引上的布尔标志
$as_odd
指示当前迭代在奇数索引上的布尔标志
这些提供的额外的变量和所有在foreach中创建的新变量,仅仅在``foreach``范围内是可用的。如果变量存在与foreach的上下文之外, 在foreach循环的最后,值将复制到全局上下文中。
<t t-set="existing_variable" t-value="False"/>
<!-- existing_variable now False -->
<p t-foreach="[1, 2, 3]" t-as="i">
<t t-set="existing_variable" t-value="True"/>
<t t-set="new_variable" t-value="True"/>
<!-- existing_variable and new_variable now True -->
</p>
<!-- existing_variable always True -->
<!-- new_variable undefined -->
属性
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_parity }}"><t t-esc="item"/></li>
</t>
结果如下:
<li class="row even">1</li>
<li class="row odd">2</li>
<li class="row even">3</li>
t-att=mapping
如果参数是一个映射,每个(key,value)对生成一个新属性及其值:
<div t-att="{'a': 1, 'b': 2}"/>
结果如下:
<div a="1" b="2"></div>
t-att=pair
如果参数是一对(元组或2元素数组),这对的第一项是属性的名称,第二项是值:
<div t-att="['a', 'b']"/>
结果如下:
<div a="b"></div>
设置变量
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>
当我们使用esc指令时,内容被转义)注
使用此操作的结果是raw指令的一个重要用
调用子模板
QWeb模板可用于顶级的渲染, 但也可以从另一个使用t-call指令的模板(t避免重复或给名字的部分模板) 而被使用 :
<t t-call="other-template"/>
这将调用父模板的执行上下文, 如果other_template
被定义为:
<p><t t-value="var"/></p>
上面的调用将被渲染为 <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>
<!-- "var" does not exist here -->
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>
Python
专用指令
资产包
“智能记录”字段格式化
t-field
指令只能用于当执行在一个“聪明”记录(browse
method方法返回结果)上的字段访问 (a.b
) 。它能够自动基于字段类型进行格式化,并集成了网站富文本编辑。
t-options可使用自定义字段,最常用的选项是widget,其他选项字段或控件的依赖
调试
t-debug
调用调试器使用PDB的set_trace
API. 这个参数应该是一个模块的名称,在这个模块上set_trace
方法被调用:
<t t-debug="pdb"/>
相当于importlib.import_module("pdb").set_trace()
帮助者
基于请求
对QWeb大多数Python端的使用是在控制器中 (且在HTTP请求期间),在这种情况下,模板存储在数据库中 (做为视图) 可以通过调用odoo.http.HttpRequest.render()
而进行一般性的渲染:
response = http.request.render('my-template', {
'context_value': 42
})
这将自动创建一个从控制器返回(或进一步定制以适应)Response
对象
基于视图
在更深的层次上比以前的助手是在ir.ui.view上的render方法:
render(cr, uid, id[, values][, engine='ir.qweb][, context])
通过数据库id或外部id呈现一个QWeb 视图/模板。模板从ir.ui.view记录自动加载。
在呈现上下文中设置一些默认值:
request
当前 WebRequest
对象,如果真有的话
debug
当前请求(如果有的话)是否处于debug
模式
url编码实用函数
相应的标准库模块
相应的标准库模块
相应的标准库模块
详见模版
keep_query
keep_query
帮助这函数
参数
- values -- 上下文值传递给QWeb渲染
- engine (
str
) -- 用于渲染的Odoo模型名称,可以用来扩展或自定义本地的QWeb (通过创建一个“新的”基于变化ir.qweb的qweb)
Javascript
专用指令
定义模板
t-name
指令只能放在模板文件的顶部(直接将其指向文档根):
<templates>
<t t-name="template-name">
<!-- template code -->
</t>
</templates>
它不需要其他参数,但可以与<t>元素或其他元素一起使用。如果有一个<t>元素,则<t>应该有一个单独的子元素。
模板名是一个任意字符串,尽管当多个模板相关时(例如所谓的子模板),习惯上使用点分隔的名称来表示层次关系。
模板继承
模板继承被用来改变现有的模板原状,例如将信息添加到由其他模块创建的模板。
模板继承是通过t-extend指令以模板的名称作为参数进行修改。
然后改变通过使用任意数量的t-jquery子指令来执行:
<t t-extend="base.template">
<t t-jquery="ul" t-operation="append">
<li>new element</li>
</t>
</t>
t-jquery
指令接受CSS选择器。这个选择器是用于扩展的模板选择上下文节点,它指明了t-operation
指令应用:
append
节点的主体被附加在上下文节点的结尾(在上下文节点的最后一个子节点之后)
prepend
节点的主体被附加到上下文节点的头部 (在上下文节点的第一个子节点之前)
before
节点的主体被插入到上下文节点之前
after
节点的主体是在上下文节点之后插入的
inner
节点的主体替换了上下文节点的子节点
replace
节点的主体用于替换上下文节点本身
无操作
如果没有指定t-operation
,模板体被解释为JavaScript代码,并使用作为this的上下文节点执行
警告
虽然比其他操作更强大,但这种模式也难以调试和维护,建议避免使用它
调试
javascript QWeb实现提供了一些调试钩子:
t-log
以表达式的参数,评价表达在渲染并用console.log记录其结果:
<t t-set="foo" t-value="42"/>
<t t-log="foo"/>
将打印 42
到控制台
t-debug
在模板呈现期间触发调试器断点
<t t-if="a_test">
<t t-debug="">
</t>
如果调试处于活动状态(准确的条件取决于浏览器及其开发工具),将停止执行
t-js
节点的主体是在模板呈现期间执行的JavaScript代码。接收一个 context
参数, 它是在t-js体中将会有效的进行渲染上下文下的名称:
<t t-set="foo" t-value="42"/>
<t t-js="ctx">
console.log("Foo is", ctx.foo);
</t>
帮助者
core.qweb
(核心是 web.core
模块) 一个所有模块定义的模版文件加载的QWeb2.Engine()
实例,参考了标准帮助者对象 _
(下划线), _t
(翻译功能) 和 JSON。
core.qweb.render
可以用来轻松渲染基本模块模板
API
class QWeb2.Engine()
QWeb的“渲染”,操作大部分的QWeb的逻辑(加载、解析、编译和渲染的模板)。
OpenERP Web实例化的一个核心模块的用户,并输出到 core.qweb
。 它还加载各种模块的模板文件到QWeb实例
QWeb2.Engine()
还充当“模板命名空间”
QWeb2.Engine.render(template[, context])
将先前加载的模板呈现到字符串中,使用context(如果提供)查找模板呈现期间访问的变量(例如要显示的字符串)
参数
- template (
String
) -- 要呈现的模板的名称 - context (
Object
) -- 用于模板呈现的基本命名空间
返回
字符串
引擎暴露出其他的方法,在某些情况下可能是有用的 (如果你需要一个单独的模板的命名空间,在OpenERP Web中,看板视图得到自己的 QWeb2.Engine()
实例,因此它们的模板不会和更一般的“模块”模板相抵触):
QWeb2.Engine.add_template(templates)
加载一个QWeb实例的模板文件(模板集)。模板可以指定为:
An XML string
QWeb 将尝试将其解析为XML文档,然后加载它
A URL
QWeb将尝试下载URL内容,然后加载生成的XML字符串
A Document
or Node
QWeb将遍历文档的第一级(所提供根的子节点)并加载任何命名模板或模板重写
QWeb2.Engine()
还公开了行为定制的各种属性:
QWeb2.Engine.prefix
在解析过程中用来识别指令的前缀。一个字符串。默认情况下, t
QWeb2.Engine.debug
布尔标志将引擎置于“调试模式”。通常,QWeb截取任何模板时执行抛出错误。在调试模式下,所有异常都会在不拦截的情况下进行
QWeb2.Engine.jQuery
模板继承过程中使用的jQuery实例。默认值为window.jQuery
QWeb2.Engine.preprocess_node
一个 Function
。 如果存在,在编译每个DOM节点到模板代码之前调用。在OpenERP Web中,这是用来自动翻译的文字内容和模板中的一些属性。默认值为 null
[1] 它和 Genshi很相似, 尽管它不使用(也不支持)XML名称空间
[2] 虽然它使用了一些其他的,或者是出于历史原因,或者因为它们更适合于用例。Odoo 9.0 仍然依赖于Jinja 和Mako.
ps:有翻译不当之处,欢迎留言指正。
原文地址:https://www.odoo.com/documentation/10.0/reference/qweb.html