QWeb模板

QWeb是Odoo[#othertemplates]_使用的主要模板引擎。它是一个XML模板引擎1,主要用于生成HTML_片段和页面。

模板指令被指定为以 t- 为前缀的 XML 属性,例如 条件语句t-if,元素和其他属性直接呈现。

为了避免元素渲染,还提供了一个占位符元素 <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>

数据输出

QWeb 的输出指令 out 会自动对其输入进行 HTML 转义,在显示用户提供的内容时限制 XSS 风险。

out takes an expression, evaluates it and injects the result in the document:

<p><t t-out="value"/></p>

使用值 value 设置为 42 渲染的结果为:

<p>42</p>

请参阅 高级输出 以获取更高级的主题(例如注入原始HTML等)。

条件语句

QWeb 有一个条件指令 if,它评估给定的表达式作为属性值:

<div>
    <t t-if="condition">
        <p>ok</p>
    </t>
</div>

如果条件为真,则呈现该元素:

<div>
    <p>ok</p>
</div>

但如果条件为假,则从结果中删除它:

<div>
</div>

条件渲染适用于指令的承载者,它不必是 <t>:

<div>
    <p t-if="condition">ok</p>
</div>

将会得到与前一个示例相同的结果。

还有额外的条件分支指令 t-elift-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>

循环

QWeb有一个迭代指令 foreach ,它接受一个返回要迭代的集合的表达式和第二个参数 t-as ,用于提供迭代的”当前项目”的名称:

<t t-foreach="[1, 2, 3]" t-as="i">
    <p><t t-out="i"/></p>
</t>

将被渲染为:

<p>1</p>
<p>2</p>
<p>3</p>

与条件类似, foreach 应用于带有指令属性的元素,并且

<p t-foreach="[1, 2, 3]" t-as="i">
    <t t-out="i"/>
</p>

与前一个示例等效。

foreach can iterate on an array (the current item will be the current value) or a mapping (the current item will be the current key). Iterating on an integer (equivalent to iterating on an array between 0 inclusive and the provided integer exclusive) is still supported but deprecated.

除了通过 t-as 传递的名称外, foreach 还提供了一些其他变量用于不同的数据点:

警告

$as 将被替换为传递给 t-as 的名称

$as_all (deprecated)

正在迭代的对象

注解

此变量仅在JavaScript QWeb中可用,而不在Python中可用。

$as_value

当前迭代的值,对于列表和整数与 $as 相同,但对于映射,它提供值(而 $as 提供键)

$as_index

当前迭代的索引(第一个迭代项的索引为0)

$as_size

如果可用,返回集合的大小

$as_first

当前项是否为迭代的第一个项(等同于 $as_index == 0)

$as_last

当前项是否为迭代的最后一项(等同于 $as_index + 1 == $as_size),需要迭代器的大小可用

$as_parity (deprecated)

either "even" or "odd", the parity of the current iteration round

$as_even (deprecated)

一个布尔标志,指示当前迭代轮次是否在偶数索引上

$as_odd (deprecated)

一个布尔标志,指示当前迭代轮次是否为奇数索引

这些额外提供的变量和在 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 (属性)指令完成的,该指令有三种不同的形式:

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-out="item"/>
    </li>
</t>

将被渲染为:

<li class="row even">1</li>
<li class="row odd">2</li>
<li class="row even">3</li>

小技巧

有两种等效的格式字符串语法: "plain_text {{code}}" (也称为 jinja 风格)和 "plain_text #{code}" (也称为 ruby 风格)。

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-out="foo"/>
    

    将打印 3

  • 如果没有 t-value 属性,则节点的主体将被渲染并设置为变量的值:

    <t t-set="foo">
        <li>ok</li>
    </t>
    <t t-out="foo"/>
    

调用子模板

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" does not exist here -->

The body of the call directive can be arbitrarily complex (not just set directives), and its rendered form will be available within the called template as a magical 0 variable:

<div>
    This template was called with content:
    <t t-out="0"/>
</div>

被这样调用:

<t t-call="other-template">
    <em>content</em>
</t>

将导致:

<div>
    This template was called with content:
    <em>content</em>
</div>

高级输出

默认情况下, out 应该对需要转义的内容进行 HTML 转义,以保护系统免受 XSS 攻击。

不需要转义的内容将直接注入到文档中,并可能成为文档实际标记的一部分。

唯一的跨平台“安全”内容是 t-call 或使用 t-set 与“body”(而不是 t-valuet-valuef)一起使用的输出。

Python

通常情况下,您不必过于关心:对于需要生成“安全”内容的API,应自动生成,事情应该透明地运行。

对于需要更清晰的情况,以下 API 输出安全内容,这些内容默认情况下不会在注入模板时被重新转义:

  • HTML fields.

  • html_escape()markupsafe.escape() (它们是 别名,没有双重转义的风险)。

  • html_sanitize().

  • markupsafe.Markup.

    警告

    markupsafe.Markup 是一个不安全的 API,它是一个 断言,你希望内容是标记安全的,但不能保证,应该小心使用。

  • to_text() 不会将内容标记为安全,但不会从安全内容中删除该信息。

使用 Markup 创建安全内容

See the official documentation for explanations, but the big advantage of Markup is that it’s a very rich type overriding str operations to automatically escape parameters.

这意味着通过在字符串文字上使用 Markup ,可以轻松创建 安全的 HTML 片段,并且可以“格式化”用户提供的(因此可能不安全的)内容:

>>> Markup('<em>Hello</em> ') + '<foo>'
Markup('<em>Hello</em> &lt;foo&gt;')
>>> Markup('<em>Hello</em> %s') % '<foo>'
Markup('<em>Hello</em> &lt;foo&gt;')

虽然这是一件非常好的事情,但请注意,有时候效果可能会很奇怪:

>>> Markup('<a>').replace('>', 'x')
Markup('<a>')
>>> Markup('<a>').replace(Markup('>'), 'x')
Markup('<ax')
>>> Markup('<a&gt;').replace('>', 'x')
Markup('<ax')
>>> Markup('<a&gt;').replace('>', '&')
Markup('<a&amp;')

小技巧

大多数内容安全的API实际上返回一个 Markup ,带有所有相关的内容。

Javascript

警告

由于缺乏运算符重载,:js Markup 类型比 Markup 类型更加有限。

因此它也不会覆盖方法,任何涉及到 Markup() 的操作都会返回一个普通的 String() (实际上甚至不是那样,而是一个“原始字符串”)。

这意味着回退是安全的,但是在使用 Markup() 对象时很容易触发双重转义。

强制双重转义

如果内容被标记为安全的,但由于某些原因仍需要进行转义(例如打印HTML字段的标记),则可以将其转换回普通字符串以“去除”安全标志,例如在Python中使用 str(content) ,在Javascript中使用 String(content)

注解

因为 Markup 类型比 Markup() 类型更丰富,一些操作会从 Markup() 中删除安全信息,但不会从 Markup 中删除,例如在 Python 中的字符串连接('' + content)将导致一个具有正确转义的 Markup,而在 Javascript 中将产生一个未经转义的 String()

已弃用的输出指令

esc

An alias for out, would originally HTML-escape its input. Not yet formally deprecated as the only difference between out and esc is that the latter is a bit unclear / incorrect.

raw

一个永远不会转义其内容的版本 out。内容会原样输出,无论是否安全。

15.0 版后已移除: 使用 outmarkupsafe.Markup 值代替。

t-raw 被弃用,因为随着生成内容的代码的演变,很难追踪它将用于标记,导致更复杂的审查和更危险的疏忽。

Python

独占指令

资源包

“智能记录”字段格式化

t-field 指令只能在对“智能”记录(browse 方法的结果)执行字段访问(a.b)时使用。它能够根据字段类型自动进行格式化,并集成在网站的富文本编辑中。

t-options 可用于自定义字段,最常见的选项是 widget,其他选项取决于字段或小部件。

调试

t-debug

使用 PDB 的 set_trace API 调用调试器。参数应该是一个模块的名称,在该模块上调用 set_trace 方法:

<t t-debug="pdb"/>

等同于 importlib.import_module("pdb").set_trace()

渲染缓存:

t-cache="key_cache" tags part of template to be cached at rendering time. Every sub-directives will be call only during the first rendering. It means that the sql queries excecuted during the rendering of those sub-directives are also done only once.

t-nocache="documentation" tags part of template to be render every time. The content can only use the root values.

为什么和何时使用 t-cache?

该指令用于加速渲染,通过缓存最终文档的部分内容,可以避免对数据库的查询。但是,应该谨慎使用 t-cache ,因为它会不可避免地使模板变得复杂(例如,它们对 t-set 的理解)。

然而,为了真正节省数据库查询,可能需要使用惰性求值的值来渲染模板。如果这些惰性求值的值用于缓存部分,则如果该部分可用于缓存,则不会对其进行求值。

The t-cache directive is useful for template parts using values that depend on a limited amount of data. We recommend to analyze the rendering of the template with the profiler (by activating the “Add qweb directive context” option). Passing lazy values to the rendering in controllers allow you to display the directives using these values and triggering the queries.

使用这样的缓存的一个问题是使其对不同的用户可用(不同的用户应该以相同的方式呈现缓存的部分)。另一个潜在问题是在必要时使其条目无效。对于后者,应明智地选择 键表达式 。例如,使用记录集的 write_date 可以使缓存键过时,而无需显式地从缓存中丢弃它。

还应注意到 t-cache 部分中的值是有作用域的。这意味着,如果在模板的这部分中有 t-set 指令,则在其后面呈现的内容可能与没有 t-cache 指令时不同。

如果在 t-cache 内部有一个 t-cache 会怎么样?

这些部分被缓存。每个部分只包含其渲染对应的字符串。因此,内部的 t-cache 可能会被较少读取,其缓存键不一定会被使用。如果必须这样做,则可能需要添加一个 t-nocache (在同一节点或父节点上)。

t-nocache 用于什么?

如果您想使用 t-cache 缓存模板的一部分,但是某个小部分必须保持动态并在缓存时进行评估。然而,在 t-nocache 中的部分将无法访问模板的 t-set 值。只有控制器提供的值可以在那里访问。例如,菜单被缓存,因为它始终是相同的,并且需要时间来渲染(使用 qweb 上下文的性能开发工具可以进行调查)。然而,在菜单中,我们希望电子商务购物车始终保持最新状态。因此,有一个 t-nocache 来保持此部分动态。

t-cache 的基础

The t-cache directive allows you to store the rendered result of a template. The key expression (eg 42: t-cache="42") will be evaluated as a python expression. This will be used to generate the cache key. So there can be different cache values (cached render part) for the same template part. If the key expression is a tuple or a list, it will be searched when generating the cache key. If one or more recordsets are returned by the key expression, then the model, ids and their corresponding write_date will be used to generate the cache key. Special case: If the key expression returns a Falsy value, then the content will not be cached.

示例:

<div t-cache="record,bool(condition)">
    <span t-if="condition" t-field="record.partner_id.name">
    <span t-else="" t-field="record.partner_id" t-options-widget="contact">
</div>

在这种情况下,缓存中可能存在与已返回的每个记录对应的值(字符串),包括 true 条件和 false 条件。如果一个模块修改了记录,修改了 write_date,缓存的值将被丢弃。

t-cache 和作用域值 (t-set, t-foreach…)

t-cache 中的值是有作用域的,这意味着在父节点中有或没有 t-cache 之间的行为会发生变化。不要忘记考虑到 Odoo 使用了很多模板,t-call 和视图继承。因此,添加 t-cache 可能会修改您在编辑时看不到的模板的渲染。(t-foreach 就像每次迭代的 t-set

示例:

<div>
    <t t-set="a" t-value="1"/>
    <inside>
        <t t-set="a" t-value="2"/>
        <t t-out="a"/>
    </inside>
    <outside t-out="a"/>

    <t t-set="b" t-value="1"/>
    <inside t-cache="True">
        <t t-set="b" t-value="2"/>
        <t t-out="b"/>
    </inside>
    <outside t-out="b"/>
</div>

将渲染:

<div>
    <inside>2</inside>
    <outside>2</inside>

    <inside>2</inside>
    <outside>1</inside>
</div>

t-nocache 的基础

在带有 t-nocache 属性的节点中包含的模板部分不会被缓存。因此,此内容是 动态的 ,会被系统地渲染。但是,可用的值是由控制器(调用 _render 方法时)提供的。

示例:

<section>
    <article t-cache="record">
        <title><t t-out="record.name"/> <i t-nocache="">(views: <t t-out="counter"/>)</i></titlle>
        <content t-out="record.description"/>
    </article>
</section>

将渲染(计数器=1):

<section>
    <article>
        <title>The record name <i>(views: 1)</i></titlle>
        <content>Record description</content>
    </article>
</section>

这里包含容器的 <i> 标签将始终被呈现,而其余部分将作为缓存中的单个字符串。

t-nocache 和作用域根值 (t-set, t-foreach…)

The contents of the t-nocache tag can be used for documentation and to explain why the directive is added. The values are scoped into t-nocache, these values are root values only (values provided by the controller and/or when calling the _render method of ir.qweb). t-set can be done in the template part, but will not be available elsewhere.

示例:

<section>
    <t t-set="counter" t-value="counter * 10"/>
    <header t-nocache="">
        <t t-set="counter" t-value="counter + 5"/>
        (views: <t t-out="counter"/>)
    </header>
    <article t-cache="record">
        <title><t t-out="record.name"/> <i t-nocache="">(views: <t t-out="counter"/>)</i></titlle>
        <content t-out="record.description"/>
    </article>
    <footer>(views: <t t-out="counter"/>)</footer>
</section>

将渲染(计数器=1):

<section>
    <header>
        (views: 6)
    </header>
    <article>
        <title>The record name <i>(views: 1)</i></titlle>
        <content>Record description</content>
    </article>
    <footer>(views: 10)</footer>
</section>

在这里,包含容器的 <i> 标签将始终被渲染。而其余部分将作为缓存中的单个字符串。计数器不会被 t-set 之外的 t-nocache 更新。

t-nocache-* 在缓存中添加一些基本值

为了能够使用在模板中生成的值,可以对它们进行缓存。指令的使用方式为 t-nocache-*="expr",其中 * 是所选值的名称,expr 是 Python 表达式,因此结果将被缓存。缓存的值必须是原始类型。

示例:

<section t-cache="records">
    <article t-foreach="records" t-as="record">
        <header>
            <title t-field="record.get_method_title()"/>
        </header>
        <footer t-nocache="This part has a dynamic counter and must be rendered all the time."
                t-nocache-cached_value="record.get_base_counter()">
            <span t-out="counter + cached_value"/>
        </footer>
    </article>
</section>

变量 cached_value 被缓存,使用了 t-cache="records" 的缓存模板部分,并且每次都会添加到作用域根值中。

辅助函数

基于请求的

大多数在Python端使用QWeb的情况是在控制器中(以及在HTTP请求期间),在这种情况下,存储在数据库中的模板(如: 视图 )可以通过调用 odoo.http.HttpRequest.render() 轻松地渲染:

response = http.request.render('my-template', {
    'context_value': 42
})

这将自动创建一个 Response 对象,可以从控制器返回(或进一步自定义以适应)。

基于视图的

比起之前的帮助程序,更深层次的是在 ir.qweb 上使用 _render 方法(使用数据表),以及公共模块方法 render (不使用数据库):

_render(id[, values])

通过数据库ID或 外部ID 渲染QWeb视图/模板。模板会自动从 ir.qweb 记录中加载。

_prepare_environment 方法在渲染上下文中设置了一些默认值。http_routingwebsite 插件也有它们所需的默认值。您可以使用 minimal_qcontext=False 选项来避免 这个默认值,就像公共方法 render 一样:

request

当前的 Request 对象(如果有的话)

debug

当前请求(如果有)是否处于 调试 模式

quote_plus

URL编码实用函数

json

相应的标准库模块

time

相应的标准库模块

datetime

相应的标准库模块

relativedelta

查看模块

keep_query

the keep_query helper function

参数
  • values – 传递给 QWeb 用于渲染的上下文值

  • engine (str) – 用于渲染的Odoo模型名称,可用于在本地扩展或自定义QWeb(通过基于 ir.qweb 创建“新”QWeb并进行更改)

render(template_name, values, load, **options)
load(ref)()

返回 etree 对象,引用

Javascript

独占指令

定义模板

The t-name directive can only be placed at the top-level of a template file (direct children to the document root):

<templates>
    <t t-name="template-name">
        <!-- template code -->
    </t>
</templates>

它不需要其他参数,但可以与 <t> 元素或任何其他元素一起使用。对于 <t> 元素, <t> 应该只有一个子元素。

模板名称是任意字符串,但是当多个模板相关联(例如称为子模板)时,通常使用点分隔的名称来表示层次关系。

模板继承

模板继承用于以下两种情况:
  • 修改现有模板,例如向模板添加信息

由其他模块创建。
  • 从给定的父模板创建一个新模板

模板继承通过使用两个指令来执行:
  • t-inherit which is the name of the template to inherit from,

  • t-inherit-mode 是继承的行为方式:可以将其设置为 primary 以从父模板创建新的子模板,或者将其设置为 extension 以直接修改父模板。

还可以指定可选的 t-name 指令。如果在主模式下使用,它将是新创建的模板的名称,否则它将作为注释添加到转换后的模板中,以帮助追溯继承关系。

对于继承本身,更改是使用xpaths指令完成的。请参阅XPATH_文档以获取可用指令的完整集合。

主要继承(子模板):

<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>

旧继承机制(已弃用)

模板继承是通过 t-extend 指令执行的,该指令以要更改的模板名称作为参数。

当与 t-name 结合使用时,指令 t-extend 将作为主要继承;当单独使用时,将作为扩展继承。

在这两种情况下,都可以使用任意数量的 t-jquery 子指令来执行修改操作:

<t t-extend="base.template">
    <t t-jquery="ul" t-operation="append">
        <li>new element</li>
    </t>
</t>

The t-jquery directives takes a CSS selector. This selector is used on the extended template to select context nodes to which the specified t-operation is applied:

append

节点的主体被追加到上下文节点的末尾(在上下文节点的最后一个子节点之后)

prepend

节点的主体被插入到上下文节点之前(插入到上下文节点的第一个子节点之前)

before

节点的主体被插入到上下文节点之前

after

节点的主体被插入到上下文节点之后

inner

节点的主体替换上下文节点的子节点

replace

节点的主体用于替换上下文节点本身

attributes

节点的主体应该是任意数量的 attribute 元素,每个元素都有一个 name 属性和一些文本内容,上下文节点的命名属性将被设置为指定的值(如果已存在,则被替换,如果不存在,则被添加)

没有操作

如果未指定 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

(core 是 web.core 模块) 一个 QWeb2.Engine() 的实例,加载了所有模块定义的模板文件,并引用了标准的辅助对象 _ (下划线),_t (翻译函数) 和 JSON

core.qweb.render 可以用于轻松渲染基本模块模板

API

class QWeb2.Engine()

QWeb的“渲染器”处理大部分QWeb的逻辑(加载、解析、编译和渲染模板)。

Odoo Web 在核心模块中为用户实例化一个,并将其导出到 core.qweb。它还将各个模块的所有模板文件加载到该 QWeb 实例中。

一个 QWeb2.Engine() 也可以作为一个 “template namespace”。

QWeb2.Engine.QWeb2.Engine.render(template[, context])

使用 context (如果提供)将预先加载的模板呈现为字符串,以查找在模板呈现期间访问的变量(例如要显示的字符串)。

参数
  • template (String()) – 要渲染的模板名称

  • context (Object()) – 用于模板渲染的基本命名空间

返回

字符串

The engine exposes an other method which may be useful in some cases (e.g. if you need a separate template namespace with, in Odoo Web, Kanban views get their own QWeb2.Engine() instance so their templates don’t collide with more general “module” templates):

QWeb2.Engine.QWeb2.Engine.add_template(templates)

在 QWeb 实例中加载一个模板文件(一组模板)。模板可以指定为:

一个 XML 字符串

QWeb 将尝试将其解析为 XML 文档,然后加载它。

一个URL

QWeb将尝试下载URL内容,然后加载生成的XML字符串。

一个 DocumentNode

QWeb将遍历文档的第一层(提供的根节点的子节点),并加载任何命名模板或模板覆盖。

一个 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 namespaces _

2

尽管出于历史原因或者因为它们更适合特定的用例,Odoo使用了一些其他的模板引擎。但是Odoo 9.0仍然依赖于Jinja_和Mako