QWeb是Odoo 2使用的主要模板引擎。它是一个XML模板引擎1,主要用于生成HTML 片段和页面。
模板指令被指定为前缀的XML属性t-,例如t-if为条件句,与直接渲染的元素和其他属性。
为了避免元素呈现,也可以使用占位符元素,该元素执行其指令但不会生成任何输出:
<t t-if = “condition” >
<p>测试</ p>
</ t>
将导致:
<p>测试</ p>
如果condition是真的,但是:
<div t-if = “condition” >
<p>测试</ p>
</ div>
将导致:
<div>
<p>测试</ p>
</ div>
数据输出
QWeb有一个主输出指令,当显示用户提供的内容时,它会自动HTML转义其限制XSS风险的内容:esc。
esc 获取表达式,对其进行评估并打印内容:
<p> <t t-esc = “value” /> </ p>
使用value设置为42yield 的值进行渲染:
<p> 42 </ p>
还有一个其他输出指令raw,它们的行为分别相同,esc但不对其输出进行HTML转义。显示单独构造的标记(例如,来自函数)或已经消毒的用户提供的标记可能是有用的。
条件语句
QWeb有一个条件指令if,用于计算作为属性值给出的表达式:
<div>
<t t-if = “condition” >
<p> ok </ p>
</ t>
</ div>
如果条件为真,则呈现元素:
<div>
<p> ok </ p>
</ div>
但如果条件为false,则从结果中删除:
<div>
</ div>
条件呈现适用于指令的承载,不必是:
<div>
<p t-if = “condition” > ok </ p>
</ div>
将给出与前一个示例相同的结果。
额外的条件分支指令t-elif和t-else也可用:
<div>
<p t-if = “user.birthday == today()” >祝你生日愉快!</ p>
<p t-elif = “user.login =='root'” >欢迎大师!</ p>
<p t-else = “” >欢迎!</ 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和0之间的数组上迭代和提供的整数独占)。
除了传递的名称外t-as,foreach还为各种数据点提供了一些其他变量:
警告
$as 将被传递给的名称所取代 t-as
$as_all
迭代的对象
此变量仅适用于JavaScript QWeb,而不适用于Python。
a
s
v
a
l
u
e
当
前
迭
代
值
,
与
as_value 当前迭代值,与
asvalue当前迭代值,与as列表和整数相同,但对于映射,它提供值(在哪里$as提供键)
$as_index
当前迭代索引(迭代的第一项索引为0)
$as_size
集合的大小(如果可用)
$as_first
当前项是否是迭代的第一个(相当于 $as_index == 0)
a
s
l
a
s
t
当
前
项
是
否
是
迭
代
的
最
后
一
项
(
相
当
于
)
,
要
求
i
t
e
r
a
t
e
e
的
大
小
可
用
as_last 当前项是否是迭代的最后一项(相当于 ),要求iteratee的大小可用
aslast当前项是否是迭代的最后一项(相当于),要求iteratee的大小可用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和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
如果参数是映射,则每个(键,值)对生成一个新属性及其值:
<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-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”在这里不存在 - >
call指令的主体可以是任意复杂的(不仅仅是 set指令),并且其呈现的形式将在被调用的模板中作为魔法0变量可用:
<div>
使用内容调用此模板:<t t-raw = “0” /> </ div>
被称为:
<t t-call = “other-template” >
<em> content </ em>
</ t>
将导致:
<div>
使用内容调用此模板:<em> content </ em> </ div>
python
独家指令
资产包
智能记录”字段格式化
该t-field指令只能a.b在“智能”记录(browse方法的结果)上执行字段访问()时使用。它能够根据字段类型自动格式化,并集成在网站的富文本版本中。
t-options可用于自定义字段,最常见的选项是widget,其他选项依赖于字段或小部件。
调试
t-debug
使用PDB的set_traceAPI 调用调试器。参数应该是模块的名称,在该模块上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可以从控制器返回的对象(或进一步自定义以适应)
基于视图的
在比以前的帮助程序更深层次的render方法是 ir.ui.view:
render(cr, uid, id[, values][, engine='ir.qweb][, context])
按数据库ID或外部标识呈现QWeb视图/模板。模板从ir.ui.view记录中自动加载。
在渲染上下文中设置许多默认值:
request
当前WebRequest对象,如果有的话
debug
当前请求(如果有)是否处于debug模式
quote_plus
url-encoding实用程序功能
json
相应的标准库模块
time
相应的标准库模块
datetime
相应的标准库模块
relativedelta
看模块
keep_query
该keep_query辅助函数
参数
values - 要传递给QWeb进行渲染的上下文值
engine(str) - 用于呈现的Odoo模型的名称,可用于在本地扩展或自定义QWeb(通过创建基于ir.qweb更改的“新”qweb )
使用Javascript
独家指令
定义模板
该t-name指令只能放在模板文件的顶层(将子项指向文档根目录):
<templates>
<t t-name = “template-name” >
<! - 模板代码 - >
</ t>
</ templates>
它不需要其他参数,但可以与元素或任何其他参数一起使用。使用元素,应该有一个孩子。
模板名称是任意字符串,但是当多个模板相关时(例如称为子模板),通常使用点分隔名称来指示层次关系。
模板继承
模板继承用于就地更改现有模板,例如,将信息添加到由其他模块创建的模板。
模板继承是通过t-extend指令执行的,该指令将模板的名称作为参数进行更改。
然后使用任意数量的t-jquery 子指令进行更改:
<t t-extend = “base.template” >
<t t-jquery = “ul” t-operation = “append” >
<li>新元素</ 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的大部分逻辑(加载,解析,编译和渲染模板)。
Odoo Web为核心模块中的用户实例化一个,并将其导出core.qweb。它还将各种模块的所有模板文件加载到该QWeb实例中。
A QWeb2.Engine()也用作“模板命名空间”。
QWeb2.Engine.QWeb2.Engine.render(template[, context])
使用context(如果提供)将先前加载的模板呈现给String, 以查找在模板呈现期间访问的变量(例如,要显示的字符串)。
参数
template(String) - 要呈现的模板的名称
context(Object) - 用于模板呈现的基本命名空间
返回 串
该引擎公开了另一种在某些情况下可能有用的方法(例如,如果您需要一个单独的模板命名空间,在Odoo Web中,看板视图会获得自己的QWeb2.Engine() 实例,因此它们的模板不会与更通用的“模块”模板发生冲突):
QWeb2.Engine.QWeb2.Engine.add_template(templates)
在QWeb实例中加载模板文件(模板集合)。模板可以指定为:
一个XML字符串
QWeb将尝试将其解析为XML文档,然后加载它。
一个URL
QWeb将尝试下载URL内容,然后加载生成的XML字符串。
A Document或Node
QWeb将遍历文档的第一级(提供的根的子节点)并加载任何命名的模板或模板覆盖。
A QWeb2.Engine()还公开了行为定制的各种属性:
QWeb2.Engine.QWeb2.Engine.prefix
用于在解析期间识别指令的前缀。一个字符串。默认情况下t。
QWeb2.Engine.QWeb2.Engine.debug
将引擎置于“调试模式”的布尔标志。通常,QWeb会拦截模板执行期间引发的任何错误。在调试模式下,它会在不拦截所有异常的情况下通过。
QWeb2.Engine.QWeb2.Engine.jQuery
模板继承处理期间使用的jQuery实例。默认为window.jQuery。
QWeb2.Engine.QWeb2.Engine.preprocess_node
一Function。如果存在,则在将每个DOM节点编译为模板代码之前调用。在Odoo Web中,这用于自动翻译模板中的文本内容和一些属性。默认为null。
[1]它与 Genshi类似,尽管它不使用(并且不支持) XML命名空间
[2]虽然它使用了其他一些,无论是出于历史原因还是因为它们更适合用例。Odoo 9.0仍然依赖于 Jinja和 Mako。