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
接受一個表達式,對其進行求值并將結果注入到文檔中:
<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-elif
和 t-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
可以迭代數組(當前項將是當前值)或映射(當前項將是當前鍵)。迭代整數(相當于在0(含)到提供的整數(不含)之間迭代數組)仍然受支持,但已棄用。
除了通過 t-as
傳遞的名稱之外, foreach
還提供了一些其他變量,用于各種數據點:
警告
$as
將被替換為傳遞給 t-as
的名稱
$as_all
(已棄用)正在迭代的對象
注解
此變量僅在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
(已棄用)"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
(屬性)指令完成的,該指令有三種不同的形式:
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 -->
call
指令的主體可以是任意復雜的內容(不僅僅是 set
指令),并且它的渲染形式將作為一個神奇的 0
變量在被調用的模板中可用:
<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 輸出或者使用帶有“body”的 t-set (而不是 t-value
或 t-valuef
)。
Python?
通常情況下,您不必過于關心:對于需要生成“安全”內容的API,應自動生成,事情應該透明地運行。
對于需要更清晰的情況,以下 API 輸出安全內容,這些內容默認情況下不會在注入模板時被重新轉義:
HTML字段
。html_escape()
和markupsafe.escape()
(它們是別名,不會出現雙重轉義的風險)。html_sanitize()
。markupsafe.Markup
。警告
markupsafe.Markup
是一個不安全的 API,它是一個 斷言 ,表示您希望內容是標記安全的,但不能保證,應謹慎使用。to_text()
不會將內容標記為安全的,但不會從安全內容中刪除該信息。
使用 Markup
創建安全內容?
參見官方文檔以了解詳細解釋,但 Markup
的最大優點是它是一種非常豐富的類型,可以重載 str
操作以 自動轉義參數 。
這意味著,通過在字符串文字上使用 Markup
并“格式化”用戶提供的(因此可能不安全的)內容,可以輕松創建 安全的 HTML 片段:
>>> Markup('<em>Hello</em> ') + '<foo>'
Markup('<em>Hello</em> <foo>')
>>> Markup('<em>Hello</em> %s') % '<foo>'
Markup('<em>Hello</em> <foo>')
雖然這是一件非常好的事情,但請注意,有時候效果可能會很奇怪:
>>> Markup('<a>').replace('>', 'x')
Markup('<a>')
>>> Markup('<a>').replace(Markup('>'), 'x')
Markup('<ax')
>>> Markup('<a>').replace('>', 'x')
Markup('<ax')
>>> Markup('<a>').replace('>', '&')
Markup('<a&')
小技巧
大多數內容安全的API實際上返回一個 Markup
,具有所有相關含義。
JavaScript?
警告
由于缺乏運算符重載, :js Markup
類型比 Markup
類型更加受限。
因此,它也不會覆蓋方法,任何涉及到 :js Markup
的操作都會返回一個普通的 :js String
(實際上甚至不是那樣,而是一個“原始字符串”)。
這意味著回退是安全的,但是在使用 :js Markup
對象時很容易觸發雙重轉義。
強制雙重轉義?
如果內容被標記為安全的,但由于某些原因仍需要進行轉義(例如打印HTML字段的標記),則可以將其轉換回普通字符串以“去除”安全標志,例如在Python中使用 str(content)
,在Javascript中使用 String(content)
。
注解
因為 Markup
類型比 :js Markup
更豐富,一些操作會從 :js Markup
中剝離安全信息,但不會從 Markup
中剝離,例如在 Python 中進行字符串連接( '' + content
)將導致 Markup
,而另一個操作數已經被正確轉義,而在 Javascript 中將產生一個 :js String
,在連接之前另一個操作數沒有被轉義。
已棄用的輸出指令?
esc
esc
是out
的別名,最初用于對輸入進行 HTML 轉義。目前尚未正式棄用,因為out
和esc
之間唯一的區別是后者有點不清晰/不正確。raw
一個永遠不會轉義其內容的
out
版本。無論內容是否安全,都會按原樣發出。15.0 版后已移除: 使用
markupsafe.Markup
值替代out
。由于隨著生成內容的代碼的演變,很難追蹤它將用于標記,從而導致更復雜的審查和更危險的失誤,因此
t-raw
已被棄用。
Python?
獨占指令?
資源包?
“智能記錄”字段格式化?
只有在對“智能”記錄( browse
方法的結果)執行字段訪問( a.b
)時,才能使用“ t-field
”指令。它能夠根據字段類型自動格式化,并集成在網站的富文本編輯中。
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"
標簽用于在渲染時緩存模板的一部分。每個子指令只會在第一次渲染時調用。這意味著在渲染這些子指令期間執行的 SQL 查詢也只會執行一次。
t-nocache="documentation"
標簽用于每次渲染模板的部分。內容只能使用根值。
何時何地使用 t-cache
??
該指令用于加速渲染,通過緩存最終文檔的部分內容,可以避免對數據庫的查詢。但是,應該謹慎使用 t-cache
,因為它會不可避免地使模板變得復雜(例如,它們對 t-set
的理解)。
然而,為了真正節省數據庫查詢,可能需要使用惰性求值的值來渲染模板。如果這些惰性求值的值用于緩存部分,則如果該部分可用于緩存,則不會對其進行求值。
t-cache
指令適用于使用依賴于有限數據量的值的模板部分。我們建議使用分析器(通過激活“ 添加 qweb 指令上下文 ”選項)分析模板的渲染。在控制器中將惰性值傳遞到渲染中,可以讓您使用這些值顯示指令并觸發查詢。
使用這樣的緩存的一個問題是使其對不同的用戶可用(不同的用戶應該以相同的方式呈現緩存的部分)。另一個潛在問題是在必要時使其條目無效。對于后者,應明智地選擇 鍵表達式 。例如,使用記錄集的 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
的基礎?
t-cache
指令允許您存儲模板的渲染結果。 鍵表達式 (例如42: t-cache="42"
)將被評估為Python表達式。這將用于生成 緩存鍵 。因此,對于相同的模板部分,可以有不同的 緩存值 (緩存的渲染部分)。如果 鍵表達式 是元組或列表,則在生成 緩存鍵 時將對其進行搜索。如果 鍵表達式 返回一個或多個記錄集,則將使用模型、ID及其相應的write_date生成 緩存鍵 。特殊情況:如果 鍵表達式 返回Falsy值,則不會緩存內容。
示例:
<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
…)?
t-nocache
標簽的內容可用于文檔和解釋為什么添加指令。這些值被限定在 t-nocache
中,這些值僅為根值(由控制器提供和/或調用 ir.qweb
的 _render
方法時提供的值)??梢栽谀0宀糠种袌绦?t-set
,但在其他地方不可用。
示例:
<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-nocache
之外的 t-set
更新。
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"
的緩存模板部分,并且每次都會添加到作用域根值中。
輔助函數?
基于請求的?
大多數使用QWeb的Python端是在控制器中(以及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_routing
和website
插件也有它們需要的默認值。您可以使用minimal_qcontext=False
選項來避免 這個默認值,就像公共方法render
一樣:request
當前的
Request
對象(如果有的話)debug
當前請求(如果有)是否處于
調試
模式quote_plus
URL編碼實用函數
json
相應的標準庫模塊
time
相應的標準庫模塊
datetime
相應的標準庫模塊
- relativedelta
查看模塊
keep_query
keep_query
助手函數
- 參數
values – 傳遞給 QWeb 用于渲染的上下文值
engine (str) – 用于渲染的Odoo模型名稱,可用于在本地擴展或自定義QWeb(通過基于
ir.qweb
創建“新”QWeb并進行更改)
- render(template_name, values, load, **options)?
load(ref)()
返回 etree 對象,引用
JavaScript?
獨占指令?
定義模板?
t-name
指令只能放置在模板文件的頂層(直接子級到文檔根)::
<templates>
<t t-name="template-name">
<!-- template code -->
</t>
</templates>
它不需要其他參數,但可以與 <t>
元素或任何其他元素一起使用。對于 <t>
元素, <t>
應該只有一個子元素。
模板名稱是任意字符串,但是當多個模板相關聯(例如稱為子模板)時,通常使用點分隔的名稱來表示層次關系。
模板繼承?
- 模板繼承用于以下兩種情況:
修改現有模板,例如向模板添加信息
- 由其他模塊創建。
從給定的父模板創建一個新模板
- 模板繼承通過使用兩個指令來執行:
t-inherit
是要繼承的模板名稱。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>
指令 t-jquery
接受一個 CSS 選擇器。該選擇器用于在擴展模板中選擇 上下文節點 ,并將指定的 t-operation
應用于這些節點:
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>
輔助函數?
API?
- class QWeb2.Engine()?
QWeb的“渲染器”處理大部分QWeb的邏輯(加載、解析、編譯和渲染模板)。
Odoo Web 在核心模塊中為用戶實例化一個 QWeb 對象,并將其導出到
core.qweb
。它還將各個模塊的所有模板文件加載到該 QWeb 實例中。一個 :js
QWeb2.Engine
同時也作為一個“模板命名空間”。- QWeb2.Engine.QWeb2.Engine.render(template[, context])?
使用
context
(如果提供)將預先加載的模板呈現為字符串,以查找在模板呈現期間訪問的變量(例如要顯示的字符串)。- 參數
template (
String()
) – 要渲染的模板名稱context (
Object()
) – 用于模板渲染的基本命名空間
- 返回
字符串
引擎還公開了另一個方法,在某些情況下可能會很有用(例如,如果您需要一個單獨的模板命名空間,在Odoo Web中,看板視圖會獲得自己的 :js
QWeb2.Engine
實例,因此它們的模板不會與更一般的“模塊”模板發生沖突):- QWeb2.Engine.QWeb2.Engine.add_template(templates)?
在 QWeb 實例中加載一個模板文件(一組模板)。模板可以指定為:
- 一個 XML 字符串
QWeb 將嘗試將其解析為 XML 文檔,然后加載它。
- 一個URL
QWeb將嘗試下載URL內容,然后加載生成的XML字符串。
- 一個
Document
或Node
QWeb將遍歷文檔的第一層(提供的根節點的子節點),并加載任何命名模板或模板覆蓋。
A :js
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
- 2
盡管出于歷史原因或者因為它們更適合特定的用例,Odoo使用了一些其他的模板引擎。但是Odoo 9.0仍然依賴于Jinja_和Mako。