QWEB
QWeb是Odoo2使用的主要模板引擎。 它是一个XML模板引擎1,主要用于生成HTML片段和页面。
模板指令被指定为前缀为t-
的XML属性,例如t-if
for conditionals,其中元素和其他属性直接呈现。
为了避免元素呈现,占位符元素<t>
也可用,它执行其指令但不会生成任何输出:
<t t-if="condition">
<p>Test</p>
</t>
将导致:
<p>Test</p>
如果condition
为真,但是:
<div t-if="condition">
<p>Test</p>
</div>
将导致:
<div>
<p>Test</p>
</div>
data output
QWeb有一个主输出指令,当显示用户提供的内容时,它会自动HTML转义其限制XSS风险的内容:esc
。
esc
接受表达式,对其进行评估并打印内容:
<p><t t-esc="value"/></p>
使用设置为42的值value
进行渲染:
<p>42</p>
还有另一个输出指令raw
,其行为与esc
相同,但不对其输出进行HTML转义。 显示单独构造的标记(例如,来自功能)或已经消毒的用户提供的标记可能是有用的。
conditionals
QWeb有一个条件指令if,它用于计算作为属性值给出的表达式:
<div>
<t t-if="condition">
<p>ok</p>
</t>
</div>
如果条件为真,则呈现元素:
<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>
loops
QWeb有一个迭代指令foreach,它接受一个返回集合的表达式迭代,第二个参数t-提供用于迭代“当前项”的名称:
<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和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),要求iteratee的大小可用
$as_parity
“偶数”或“奇数”,当前迭代轮次的奇偶校验
$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 -->
attributes
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
如果参数是映射,则每个(键,值)对生成一个新属性及其值:
<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>
setting variables
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"/>
将生成&lt; li&gt; ok&lt; / li&gt;
(内容在我们使用esc
指令时被转义)
使用此操作的结果是
raw
指令的重要用例。
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-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
Exclusive directives(独家指令)
asset bundles(资产包)
"smart records" fields formatting
只有在“智能”记录(browse
方法的结果)上执行字段访问(a.b
)时,才能使用t-field指令。 它能够根据字段类型自动格式化,并集成在网站的富文本版本中。
t-options
可用于自定义字段,最常见的选项是widget
,其他选项依赖于字段或窗口小部件。
debugging
t-debug
使用PDB的set_trace
API调用调试器。 参数应该是模块的名称,在该模块上调用set_trace
方法:
相当于importlib.import_module(“pdb”)。set_trace()
Helpers
Request-based
QWeb的大多数Python端用途都在控制器中(以及在HTTP请求期间),在这种情况下,通过调用odoo.http.HttpRequest.render()
可以轻松地呈现存储在数据库中的模板(作为视图):
response = http.request.render('my-template', {
'context_value': 42
})
这会自动创建一个Response对象,该对象可以从控制器返回(或进一步自定义以适应)。
View-based
比前一个帮助器更深层次的是ir.ui.view
上的render
方法:
render(cr, uid, id[, values][, engine='ir.qweb][, context])
按数据库ID或外部ID呈现QWeb视图/模板。 模板从ir.ui.view
记录自动加载。
在渲染上下文中设置许多默认值:
request
当前的WebRequest
对象,如果有的话
debug
当前请求(如果有)是否处于调试模式
quote_plus
url编码实用程序功能
json
相应的标准库模块
time
相应的标准库模块
datetime
相应的标准库模块
relativedelta
参考模块
keep_query
keep_query
帮助函数
Parameters:values -- 要传递给QWeb进行渲染的上下文值
engine(str
)-- 用于渲染的Odoo模型的名称,可用于在本地扩展或自定义QWeb(通过创建基于带有更改的ir.qweb
的“新”qweb)
Javascript
Exclusive directives(独家指令)
defining templates
t-name
指令只能放在模板文件的顶层(将子项指向文档根目录):
<templates>
<t t-name="template-name">
<!-- template code -->
</t>
</templates>
它不需要其他参数,但可以与<t>
元素或任何其他元素一起使用。 使用<t>
元素,<t>
应该只有一个子元素。
模板名称是任意字符串,但是当多个模板相关时(例如,称为子模板),通常使用点分隔名称来指示层次关系。
template inheritance
模板继承用于就地改变现有模板,例如, 向其他模块创建的模板添加信息。
模板继承通过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
节点的主体用于替换上下文节点本身
No operation(无操作)
如果没有指定t-operation,模板体将被解释为javascript代码,并以上下文节点作为this
的形式执行
警告
虽然比其他操作更强大,但这种模式也很难调试和维护,建议避免使用它
debugging
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>
Helpers
core.qweb
(core是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
(如果提供)将先前加载的模板呈现给String,以查找在模板呈现期间访问的变量(例如,要显示的字符串)。
Arguments:
template(String
)-- 要呈现的模板的名称
context (Object)-- 用于模板渲染的基本命名空间
Returns:String
引擎公开了另一种在某些情况下可能有用的方法(例如,如果你需要一个单独的模板命名空间,在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
一个功能。 如果存在,则在将每个DOM节点编译为模板代码之前调用。 在OpenERP Web中,这用于自动翻译模板中的文本内容和一些属性。 默认为null
。
- [1]它与Genshi类似,尽管它不使用(并且不支持)XML命名空间
- [2]虽然它使用了一些其他的,无论是出于历史原因还是因为它们更适合用例。 Odoo 9.0仍然依赖于Jinja和Mako。