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
模式
quote_plus
url編碼實用函數
json
相應的标準庫子產品
time
相應的标準庫子產品
datetime
相應的标準庫子產品
relativedelta
詳見模版
keep_query
keep_query
幫助這函數
參數
- values -- 上下文值傳遞給QWeb渲染
- engine (
) -- 用于渲染的Odoo模型名稱,可以用來擴充或自定義本地的QWeb (通過建立一個“新的”基于變化ir.qweb的qweb)str
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