odoo Qweb 語法簡要記錄

整理Qweb基礎語法,翻譯自 https://www.odoo.com/documentation/13.0/reference/qweb.html

QWeb是Odoo使用的主要模板引擎。它是XML模板引擎,主要用於生成HTML片段和頁面。


引出 <t> 標籤 

模板指令被指定爲以t-爲前綴的XML屬性,例如,用於條件判斷的t-if,其元素和其他屬性將直接呈現。有時候爲了避免呈現元素,還提供了佔位符元素<t>,該元素執行其指令,但不會自身生成任何輸出。

當時用<t>標籤時,如果這裏的 condition 是 True

<t t-if="condition">
    <p>Test</p>
</t>

將會得到結果渲染到頁面:

<p>Test</p>

而當使用其他標籤(常規html標籤,非 <t> 標籤),如果這裏的 condition 是 True

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

將會得到結果渲染到頁面:

<div>
    <p>Test</p>
</div>

<t> 標籤就是用來幹這事的。


輸出指令

Qweb 有兩個輸出指令,一個主要的輸出指令 t-esc ,和一個 僞輸出指令 t-raw 。兩者的區別:t-esc 輸出的是數據庫的原始值,t-raw ,不會對特殊符號轉義,會將內容裏的標籤一起渲染到頁面。

實踐爲證,執行SQL,查看數據庫裏存了個啥:

select e_link from zerone_book where id = 1

 看到結果:

 分別使用 t-esc 和 t-raw 輸出:

<t t-esc="item.e_link"/>
<t t-raw="item.e_link"/>

 渲染結果:


條件判斷指令

Qweb使用 t-if 做條件判斷。

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

 如果條件 condition = True,會得到以下結果渲染到頁面:

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

 如果條件 condition =False,會得到以下結果渲染到頁面:

<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 有一個迭代指令 t-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>

像條件判斷指令一樣,t-foreach 適用於指令的載體,而該載體不必是<t>,得到的渲染結果是一樣的:

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

t-foreach 可以在數組(當前項爲當前值)或映射(當前項爲當前鍵)上進行迭代。


屬性

QWeb可以即時計算屬性,並在輸出節點上設置計算結果。 這可以通過t-att(屬性)指令完成,該指令以3種不同形式存在:

t-att-$name 

創建一個名爲$name的屬性,計算屬性值並將結果設置爲屬性值:

<div t-att-a="42"/>
<div t-att-style="color:red;"/>

得到渲染結果如下:

<div a="42"/>
<div style="color:red;"/>

t-attf-$name

 和前面一樣,但參數是一個格式字符串,而不僅僅是表達式,通常用於混合文字和非文字字符串:

<t t-foreach="[1, 2, 3]" t-as="item">
    <li t-attf-class="row style_{{item}}">
        <t t-esc="item"/>
    </li>
</t>

得到渲染如下:

<li class="row style_1">1</li>
<li class="row style_2">1</li>
<li class="row style_3">1</li>

注 *  在 t-attf-* 指令中使用上下文變量時,可以使用雙花括號 {{ }} 進行字符串的拼接

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允許在模板中創建變量,記憶一個計算(多次使用),給一塊數據起一個更清晰的名字等。

通過指令 t-set 實現,一般情況下,賦值使用 t-value ,像下面這樣:

<t t-set="foo" t-value="2 + 1"/>
<t t-esc="foo"/>

將會在對應dom位置渲染出 3 。

在不使用 t-value 的情況下,將會渲染節點的主體,並將其設置爲變量的值,像這樣:

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

在對應dom位置,渲染出 <li>ok</li> ,  <li>ok</li> 就相當於 t-value 的值。


調用子模板

QWeb模板可用於頂層渲染,但也可以使用指令 t-call 在另一個模板中使用它們(以避免重複或爲模板的各個部分命名)

一個 template 好像只會渲染第一個 <t t-name=""> ,在我親測中(odoo13),如果像下面這樣:

<template id="template1">
    <t t-name="old-template">
        <p>template-1</p>
    </t>

    <t t-name="new-template">
        <p>template-2</p>
        <t t-call="old-template"/>
    </t>
</template>

得到渲染結果:

<p>template-1</p>

只在頁面中,渲染出第一個 <t t-name="old-template"> 的內容,後面的 <t t-name = 'new-template' > 被忽略掉了。

所以,我將它們分別寫到不同的 template 裏,我在odoo13中,測試 t-call 的使用,t-call 的值應是 被調用子模板所在的template的 id ,代碼如下:

<template id="template1">
    <t t-name="old-template">
        <p>template-1</p>
    </t>
</template>

<template id="template2">
    <t t-call="模塊名.template1"/>
    <t t-name="new-template">
        <p>template-2</p>
    </t>
</template>

 

字段

t-field 此指令 不能 在 t 標籤中使用

# 此接口返回3條最新新聞
@http.route('/news/top/3')
def zerone_retrun_3_top_news(self, **kwargs)
    recs = http.request.env["zerone.news"].sudo().search([], order="id desc", limit=3)
    return http.request.render('zerone.new3_news',{'news':recs})
<template id="new3_news">
    <t t-foreach="news" t-as="item">
        <a t-att-href="item.href"><p t-field="item.title"/></a>
    </t>
</template>

渲染出:

<a href="url1"><p>title1</p></a>
<a href="url2"><p>title2</p></a>
<a href="url3"><p>title3</p></a>

t-options 可用於自定義字段,最常見的選項是小部件,其他選項依賴於字段或小部件。


定義模板

使用 t-name 僞指令只能放在模板文件的頂層(將子級直接指向文檔根目錄):

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

模板繼承

模板繼承用於改變現有的模板,例如,將信息添加到其他模塊創建的模板中。

模板繼承是通過t-extend指令執行的,該指令以要更改的模板名稱作爲參數。

當t-extend與t-name結合使用時,將創建一個具有給定名稱的新模板。

在這種情況下,擴展模板不會更改,相反,僞指令定義瞭如何創建新模板。

在這兩種情況下,都可以使用任意數量的t-jquery子僞指令執行更改:

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

t-jquery指令採用CSS選擇器。 在擴展模板上使用此選擇器來選擇要應用指定t操作的上下文節點。

  • append    節點的主體附加在上下文節點的末尾(在上下文節點的最後一個子節點之後)
  • prepend   節點的主體位於上下文節點之前(在上下文節點的第一個子節點之前插入)
  • before      節點的主體被插入到上下文節點之前
  • after         節點的主體被插入到上下文節點之後
  • inner        節點的主體替換了上下文節點的子節點
  • replace    節點的主體用於替換上下文節點本身
  • attributes 節點的主體應該是任意數量的屬性元素,每個屬性元素都具有name屬性和一些文本內容,上下文節點的named屬性將設置爲指定的值(如果已經存在則替換爲該值,或者如果不存在則添加

其他

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代碼。 帶有一個上下文參數,該名稱是渲染上下文在t-js主體中可用的名稱:

<t t-set="foo" t-value="42"/>
<t t-js="ctx">
    console.log("Foo is", ctx.foo);
</t>


最後最後,如果有同學發現那裏不對,在下方留言,貼出你的demo ,因爲 odoo 官方文檔挺老了,我能動手的確實有限。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章