Odoo17 0.1常见的QWeb 模板语言指令的详细总结
Odoo QWeb 模板语言提供了许多指令 (directives) 来增强 HTML 模板的功能,使其能够动态地展示数据、进行条件判断、循环遍历、以及实现更复杂的逻辑。 这些指令都以 t-
开头作为属性添加到 HTML 标签上。
以下是一些常见的 Odoo QWeb 模板语言指令的详细总结,并附带解释和示例:
1. 条件渲染指令:
-
t-if="condition"
: 条件判断指令。只有当condition
表达式求值为真 (truthy) 时,指令所在的 HTML 元素及其内容才会被渲染。-
语法:
<tag t-if="condition"> <!-- 当 condition 为真时渲染的内容 --> </tag>
-
解释:
condition
可以是一个布尔值、一个表达式、或者一个变量。 QWeb 会评估这个条件。 如果条件为true
,非零数字
,非空字符串
,非空列表
,非空字典
等 truthy 值,则元素会被渲染。 否则,元素及其内部的内容会被完全忽略,不会出现在最终的 HTML 输出中。 -
示例:
<p t-if="user.is_admin"> 您是管理员用户。 </p> <p t-if="order_count > 0"> 您有 <t t-esc="order_count"/> 个订单。 </p>
-
-
t-elif="condition"
:else if
条件判断指令,必须紧跟在t-if
或另一个t-elif
之后。 当之前的t-if
或t-elif
条件为假,并且当前t-elif
的condition
为真时,指令所在的 HTML 元素及其内容才会被渲染。-
语法:
<tag t-if="condition1"> <!-- 当 condition1 为真时渲染的内容 --> </tag> <tag t-elif="condition2"> <!-- 当 condition1 为假且 condition2 为真时渲染的内容 --> </tag>
-
解释:
t-elif
提供了多分支条件判断的能力。 可以有多个t-elif
指令,按顺序评估条件。 -
示例:
<p t-if="user_role == 'admin'"> 您是管理员。 </p> <p t-elif="user_role == 'manager'"> 您是经理。 </p> <p t-elif="user_role == 'user'"> 您是普通用户。 </p>
-
-
t-else=""
:else
条件指令,必须紧跟在t-if
或t-elif
之后。 当之前的所有t-if
和t-elif
条件都为假时,指令所在的 HTML 元素及其内容才会被渲染。-
语法:
<tag t-if="condition"> <!-- 当 condition 为真时渲染的内容 --> </tag> <tag t-else=""> <!-- 当 condition 为假时渲染的内容 --> </tag>
-
解释:
t-else
提供了一个默认分支,当所有前面的条件都不满足时执行。t-else
后面通常不需要写条件表达式,直接使用空字符串""
即可。 -
示例:
<p t-if="is_logged_in"> 欢迎回来,<t t-esc="user.name"/>! </p> <p t-else=""> 请先登录。 </p>
-
2. 循环指令:
-
t-foreach="items" t-as="item"
: 循环遍历指令。 用于遍历一个列表 (list) 或元组 (tuple)items
中的每个元素,并将当前元素赋值给变量item
(可以自定义变量名)。-
语法:
<tag t-foreach="items" t-as="item"> <!-- 循环体,可以使用变量 item 访问当前元素 --> </tag>
-
解释:
items
可以是一个列表、元组或者任何可迭代对象。t-as="item"
定义了循环变量item
,在循环体内部可以使用item
访问当前迭代到的元素。 -
示例:
<ul> <li t-foreach="product_list" t-as="product"> <t t-esc="product.name"/> - <t t-esc="product.price"/> </li> </ul>
-
循环上下文变量: 在
t-foreach
循环中,QWeb 还会自动提供一些特殊的上下文变量,以_
开头:-
_index
: 当前循环的索引 (从 0 开始)。 -
_first
: 布尔值,指示是否是第一次循环迭代。 -
_last
: 布尔值,指示是否是最后一次循环迭代。 -
_even
: 布尔值,指示当前索引是否为偶数。 -
_odd
: 布尔值,指示当前索引是否为奇数。 -
_size
: 循环迭代的总次数。 -
示例使用循环上下文变量:
<ul class="list-unstyled"> <li t-foreach="items" t-as="item"> <span t-if="_first">这是第一个元素: </span> <span t-esc="item"/> <span t-if="_last">, 这是最后一个元素。</span> <span t-else>, </span> </li> </ul>
-
-
-
t-foreach="dictionary" t-as="key, value"
: 循环遍历字典 (dictionary) 指令。 用于遍历一个字典dictionary
中的键值对,并将当前键赋值给key
变量,值赋值给value
变量。-
语法:
<tag t-foreach="dictionary" t-as="key, value"> <!-- 循环体,可以使用变量 key 和 value 访问当前键值对 --> </tag>
-
解释:
dictionary
必须是一个字典对象。t-as="key, value"
定义了键变量key
和值变量value
。 -
示例:
<dl> <div t-foreach="user_info" t-as="info_key, info_value"> <dt><t t-esc="info_key"/></dt> <dd><t t-esc="info_value"/></dd> </div> </dl>
-
3. 变量设置指令:
-
t-set="variable_name" t-value="expression"
: 设置变量指令。 用于在模板中定义或修改变量variable_name
,并将expression
的求值结果赋值给该变量。-
语法:
<t t-set="variable_name" t-value="expression"/>
或者 (内容作为变量值):
<t t-set="variable_name"> <!-- 这里的内容会被作为变量的值 --> <p>一些内容</p> <t t-esc="another_value"/> </t>
-
解释:
variable_name
: 要设置的变量名 (字符串)。t-value="expression"
: 要赋给变量的值的表达式。 如果省略t-value
属性,则t-set
标签内部的内容会被作为变量的值。
-
示例:
<t t-set="current_date" t-value="datetime.date.today()"/> <p>今天是: <t t-esc="current_date"/></p> <t t-set="greeting"> <h1>欢迎来到我们的网站!</h1> <p>希望您喜欢这里。</p> </t> <t t-raw="greeting"/> <!-- 使用 t-raw 来渲染 HTML 内容 -->
-
4. 值输出指令:
-
t-value="expression"
: 表达式求值指令。 用于计算expression
的值,并将结果不进行 HTML 转义直接输出到 HTML 中。 通常不直接使用t-value
进行输出,因为它不安全,容易导致 XSS 攻击。 它主要用在t-set
指令中赋值。-
语法:
<tag t-value="expression"> <!-- 通常 tag 标签内容会被忽略,输出的是 expression 的值 --> </tag>
-
解释:
expression
可以是任何 Python 表达式,可以访问模板上下文中的变量。 输出结果不会进行 HTML 转义。 -
示例 (通常不直接用于输出,多用于赋值):
<t t-set="calculated_value" t-value="price * quantity"/> <!-- 不推荐直接用于输出,除非你非常确定输出内容是安全的 --> <p t-value="unsafe_data_from_user"/>
-
-
t-esc="expression"
: 表达式求值并进行 HTML 转义 输出指令。 用于计算expression
的值,并将结果进行 HTML 转义 后输出到 HTML 中。 这是最常用的输出指令,用于安全地显示动态数据,防止 XSS 攻击。-
语法:
<tag t-esc="expression"> <!-- 通常 tag 标签内容会被忽略,输出的是 expression 的值 (HTML 转义) --> </tag>
-
解释:
expression
可以是任何 Python 表达式。 输出结果会进行 HTML 转义,例如将<
转换为<
,>
转换为>
,"
转换为"
,&
转换为&
等。 这样可以防止恶意用户注入 HTML 代码。 -
示例 (推荐使用):
<p>当前用户姓名: <t t-esc="user.name"/></p> <p>商品价格: <t t-esc="product.price"/> 元</p> <p>用户输入的内容: <t t-esc="user_input"/> <!-- 用户输入的内容会被安全转义 --></p>
-
-
t-raw="expression"
: 表达式求值并 原始输出 指令。 用于计算expression
的值,并将结果 不进行任何 HTML 转义,直接作为原始 HTML 输出到页面中。 使用t-raw
需要非常谨慎,只在输出的内容是完全可信且安全的 HTML 代码时才使用,否则可能存在 XSS 漏洞风险。 通常用于输出预先处理好的 HTML 代码片段。-
语法:
<tag t-raw="expression"> <!-- 通常 tag 标签内容会被忽略,输出的是 expression 的值 (原始 HTML) --> </tag>
-
解释:
expression
可以是任何 Python 表达式,但通常应该返回 HTML 字符串。 输出结果不会进行 HTML 转义,直接作为 HTML 代码渲染。 -
示例 (谨慎使用):
<t t-set="safe_html_content" t-value="'<h1>这是一个标题</h1><p>这是一个段落。</p>'"/> <div t-raw="safe_html_content"/> <!-- 输出 HTML 标题和段落 --> <!-- 危险示例,如果 user_generated_html 来自用户输入,则存在 XSS 漏洞 --> <!-- <div t-raw="user_generated_html"/> -->
-
5. 模板调用指令:
-
t-call="template_name"
: 调用子模板指令。 用于在当前模板中调用另一个已定义的 QWeb 模板template_name
。-
语法:
<tag t-call="template_name"> <!-- 可选: 可以使用 t-set 在这里向子模板传递参数 --> <t t-set="param1" t-value="value1"/> <t t-set="param2" t-value="value2"/> </tag>
-
解释:
template_name
是要调用的子模板的名称 (字符串)。t-call
指令会将子模板的 HTML 输出嵌入到当前模板的指定位置。 可以在t-call
标签内部使用t-set
指令来向子模板传递参数 (变量)。 子模板可以通过访问这些参数变量来接收父模板传递的数据。 -
示例:
<!-- 父模板 --> <template id="parent_template"> <div> <h1>父模板标题</h1> <p>这是父模板的内容。</p> <t t-call="child_template"> <t t-set="username" t-value="user.name"/> </t> <p>父模板内容结束。</p> </div> </template> <!-- 子模板 --> <template id="child_template"> <div> <h2>子模板标题</h2> <p>欢迎您,<t t-esc="username"/>!</p> <!-- 子模板可以使用父模板传递的 username 参数 --> </div> </template>
-
-
t-call="template_name" t-options="..."
: 调用子模板并传递选项。t-options
属性允许向子模板传递更复杂的选项字典,用于控制子模板的渲染行为。t-options
的具体内容取决于子模板的定义和期望接收的选项。-
语法:
<tag t-call="template_name" t-options="options_dict"> <!-- 可选: 仍然可以使用 t-set 传递参数,与 t-options 可以同时使用 --> </tag>
-
解释:
options_dict
是一个 Python 字典,包含了要传递给子模板的选项。 子模板需要预先定义好如何处理这些选项。 常见的t-options
用途包括:- 传递 widget 参数: 例如用于格式化日期、货币等。
- 传递格式化选项: 例如控制日期显示的格式、数字的小数位数等。
- 传递渲染模式或配置参数: 例如控制子模板的显示风格或行为。
-
示例 (假设子模板
formatted_date
接收format
选项):<template id="date_template"> <p>原始日期: <t t-esc="date_obj"/></p> <p>格式化日期 (年-月-日): <t t-call="formatted_date" t-options="{"format": "yyyy-MM-dd", "date": date_obj}"/></p> <p>格式化日期 (月/日/年): <t t-call="formatted_date" t-options="{"format": "MM/dd/yyyy", "date": date_obj}"/></p> </template> <template id="formatted_date"> <t t-set="format_str" t-value="options.get("format", "yyyy-MM-dd HH:mm:ss")"/> <!-- 默认格式 --> <t t-set="date_to_format" t-value="options.get("date")"/> <t t-esc="date_to_format.strftime(format_str) if date_to_format else ''"/> </template>
-
6. 属性指令:
-
t-att-attribute_name="expression"
: 动态属性指令。 用于动态设置 HTML 元素的属性值。attribute_name
会被替换成实际的 HTML 属性名,expression
的求值结果会作为属性值。-
语法:
<tag t-att-attribute_name="expression"> <!-- ... --> </tag>
-
解释:
attribute_name
可以是任何有效的 HTML 属性名 (例如id
,class
,href
,src
,data-*
等)。expression
的求值结果会被转换为字符串,并赋值给attribute_name
属性。 -
示例:
<div t-att-id="'product_' + product.id" t-att-class="'product-card ' + ('featured' if product.is_featured else 'normal')"> <!-- ... --> </div> <a t-att-href="'/product/' + product.id" t-att-title="product.name"> <t t-esc="product.name"/> </a>
-
-
t-attf-attribute_name="string_interpolation"
: 属性格式化指令 (Attribute Formatting)。 使用 f-string 风格的字符串插值来动态设置 HTML 元素的属性值。 更简洁易读,尤其是在属性值需要拼接多个动态部分时。-
语法:
<tag t-attf-attribute_name="f-string_expression"> <!-- ... --> </tag>
-
解释:
attribute_name
是 HTML 属性名。f-string_expression
是一个 f-string 风格的字符串,可以使用花括号{}
包裹 Python 表达式,表达式的值会被插入到字符串中。 -
示例:
<div t-attf-id="product-{product.id}" t-attf-class="product-card {'featured' if product.is_featured else 'normal'}"> <!-- ... --> </div> <a t-attf-href="/product/{product.id}" t-attf-title="{product.name}"> <t t-esc="product.name"/> </a>
-
7. 其他指令 (简要介绍):
-
t-translation="on"
: 启用模板翻译。 用于标记模板需要进行国际化 (i18n) 翻译。 通常在模板的根元素上使用。- 示例:
<template id="my_template" t-translation="on"> <!-- 模板内容,可以使用 <t t-translatable="1">...</t> 标记可翻译的文本 --> </template>
- 示例:
-
t-lang="language_code"
: 设置模板的语言。 用于指定模板渲染时使用的语言,通常用于多语言环境。- 示例:
<template id="my_template" t-lang="lang_code"> <!-- 模板内容将以 lang_code 指定的语言渲染 --> </template>
- 示例:
-
t-cache="directive"
: 模板缓存指令。 用于控制模板的缓存行为,提高性能。directive
可以是cache
,nocache
,clear
. 通常与t-key
和t-context
配合使用。 (高级用法,初学者可以先忽略) -
t-debug="expression"
: 调试指令。 用于在模板渲染过程中输出expression
的值到控制台,方便调试模板逻辑。 通常在开发阶段使用。
总结:
这些指令是 Odoo QWeb 模板语言的核心组成部分,掌握它们可以让你编写出功能强大、动态灵活的 Odoo 视图模板。 在实际开发中,你需要根据具体的需求灵活组合使用这些指令,来实现各种复杂的页面展示和交互逻辑。 建议多练习编写 QWeb 模板,并参考 Odoo 官方文档和示例代码,加深理解和掌握。