Django 模板語(yǔ)言(譯)

聲明:轉(zhuǎn)載請(qǐng)注明出處http://m.itdecent.cn/p/1664dcfd840c

最近在折騰Django,看到官網(wǎng)的Django模板文章寫(xiě)得挺詳細(xì)的,就想著翻譯下以加深自己的學(xué)習(xí)印象,如果能幫助到大家我也會(huì)感到很欣慰,以下是譯文。

這篇文章主要講解了Django模板系統(tǒng)語(yǔ)法,如果你想了解更多關(guān)于Django模板如何工作以及如何擴(kuò)展的話,可以看這篇文章The Django template language: for Python programmers.

Django 模板語(yǔ)言意在強(qiáng)大和輕松之間取得平衡。這讓那些習(xí)慣用HTML的人感到很舒服。如果你有接觸過(guò)任何其他的基于文本的模板語(yǔ)言,比如 Smarty 或者 Jinja2,那么你應(yīng)該對(duì)Django的模板語(yǔ)言倍感親切。

注意:
如果你有編程背景,或者習(xí)慣于那些混合代碼直接嵌入到HTML中的語(yǔ)言,你要記住Django模板系統(tǒng)不是將Python簡(jiǎn)單的嵌入HTML中。這是它設(shè)計(jì)的初衷:模板系統(tǒng)主要為了表達(dá)而不是程序邏輯。

Django模板系統(tǒng)提供了很多標(biāo)簽,他們的方法很像一些程序結(jié)構(gòu)--if標(biāo)簽用于布爾判斷,for標(biāo)簽用于循環(huán)等等。但是這些不是簡(jiǎn)單的作為相應(yīng)的Python代碼執(zhí)行,模板系統(tǒng)不會(huì)執(zhí)行任意Python表達(dá)式。只有下面列出的標(biāo)簽,過(guò)濾器,以及語(yǔ)句是默認(rèn)支持的(但是你可以添加自定義模板標(biāo)簽和過(guò)濾器到模板語(yǔ)言如果有需要的話)

模板

模板就是一個(gè)簡(jiǎn)單的文本文件,它可以生成任何文本格式(HTML,XML,CSV等)。

模板中包含變量和標(biāo)簽,當(dāng)模板被執(zhí)行時(shí),變量會(huì)被賦值,而標(biāo)簽是控制模板的邏輯的。

下面是個(gè)演示了一些基礎(chǔ)知識(shí)的最小模板,稍后會(huì)講解其中的每個(gè)元素。

{% extends "base_generic.html" %}

{% block title %}{{ section.title }}{% endblock %}

{% block content %}
<h1>{{ section.title }}</h1>

{% for story in story_list %}
<h2>
  <a href="{{ story.get_absolute_url }}">
    {{ story.headline|upper }}
  </a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}

注意:
為什么我們要用基于文本的而不是基于XML的模板呢?我們是想讓Django的模板語(yǔ)言用在更多的地方而不是僅僅在XML或HTML中。在聯(lián)網(wǎng)的世界里,我們把它用在電子郵箱,JavaScript以及CSV。你可以在任何文本格式中使用模板語(yǔ)言。

哦,順便說(shuō)下,讓人們編輯XML文件是很苦逼的。

變量

變量看起來(lái)像這樣:{{ 變量名 }},當(dāng)模板引擎遇到變量時(shí),會(huì)計(jì)算這個(gè)變量,并把結(jié)果賦值給它。變量名是由任何的數(shù)字,字母以及下劃線組成。點(diǎn)(“.”)也會(huì)出現(xiàn)在變量部分,當(dāng)然他有特殊用途,稍后會(huì)說(shuō)明。特別注意的是,變量名中不能出現(xiàn)空格符以及任何的標(biāo)點(diǎn)符號(hào)。

上面說(shuō)到點(diǎn)也會(huì)出現(xiàn)在變量部分,它的作用就是用來(lái)訪問(wèn)變量的屬性的。

背景

嚴(yán)格來(lái)講,當(dāng)模板系統(tǒng)遇到點(diǎn)時(shí),它會(huì)根據(jù)以下的順序查找:

  • 字典查找
  • 屬性或方法查找
  • 數(shù)字索引查找

如果結(jié)果的值是可調(diào)用,那么它就會(huì)被無(wú)參數(shù)調(diào)用。調(diào)用的結(jié)果就會(huì)變成模板中的值。

這個(gè)查找順序會(huì)對(duì)那些覆寫(xiě)了字典查找的對(duì)象造成一些不可預(yù)期的行為。比如下面是遍歷collections.defaultdict的代碼片:

{% for k, v in defaultdict.iteritems %}
   Do something with k and v here...
{% endfor %}

因?yàn)橄劝l(fā)生字典查找,所以這不可預(yù)期的行為就發(fā)生了,它會(huì)返回defaultdict的默認(rèn)值而不會(huì)調(diào)用它的iteritems()方法。在這個(gè)例子中,可以先轉(zhuǎn)化成字典。

在上面的模板例子中,{{ section.title }}會(huì)被section對(duì)象的title屬性代替。

如果你調(diào)用的變量不存在,那么模板系統(tǒng)將默認(rèn)插入空字符串‘’

注意:如果模板的上下文(context)中傳入“bar”變量,而模板中存在{{ foo.bar }}表達(dá)式,那么該表達(dá)式僅僅具有字面意思,即調(diào)用foo的bar屬性,而不會(huì)調(diào)用context中“bar”的值。

過(guò)濾器(FIlters)

你可以用filters來(lái)改變變量最終顯示的值。

過(guò)濾器看起來(lái)就像這樣{{ name|lower }}。這是將name變量通過(guò)lower過(guò)濾器全部轉(zhuǎn)換為小寫(xiě)字母。|用來(lái)調(diào)用過(guò)濾器。

過(guò)濾器可以是鏈?zhǔn)降模粋€(gè)過(guò)濾器的輸出會(huì)被用在下一個(gè)。{{ text|escape|linebreaks }} 是一種通用的形式用來(lái)將文本內(nèi)容轉(zhuǎn)義,然后再轉(zhuǎn)為<P>標(biāo)簽以適用HTML。

有些過(guò)濾器帶參數(shù)。如以下帶參過(guò)濾器:{{ bio|truncatewords:30 }}意思是只展示bio變量的前30個(gè)字符。

如果過(guò)濾器參數(shù)含有空格那么參數(shù)必須被引號(hào)引起來(lái);比如想要用逗號(hào)和空格將list中的元素拼接起來(lái),你可以這樣{{ list|join:“, ”}}。

Django提供了大約60個(gè)內(nèi)置模板過(guò)濾器。你可以到built-in filter reference.查閱更多的過(guò)濾器。為了讓你嘗試下,下面是一些常用的過(guò)濾器:

default

如果一個(gè)變量是false或者是空的,那么它的值就是你給的默認(rèn)值,否則就是變量本身的值。比如:

{{ value|default:"nothing" }}

如果變量value沒(méi)有提供,或者是空的話,上面就會(huì)顯示nothing。

length

返回變量的長(zhǎng)度。這對(duì)于字符串和列表都起作用。比如:

{{ value|length }}

如果 value是一個(gè)列表['a','b','c','d'],那么輸出就是4。

filesizeformat

將文件大小轉(zhuǎn)換為符合人們閱讀習(xí)慣的格式(如:‘13 KB’,‘4.1 MB’,‘102 bytes’等)。如下:

{{ value|filesizeformat }}

如果value是123456789的話,那么輸出將會(huì)是117.7MB。

重申下,這里僅是很少的例子,可以到built-in filter reference.查看更多完整列表。

當(dāng)然你也可以創(chuàng)建自定義模板過(guò)濾器,可以查閱這篇文章Custom template tags and filters.

提示
Django 的admin交互界面使用了所有的模板標(biāo)簽和過(guò)濾器。你可以參考這篇文章The Django admin documentation generator.

標(biāo)簽(Tags)

標(biāo)簽的形式是 {% tag %}。標(biāo)簽比變量要更復(fù)雜:有些標(biāo)簽在輸出中創(chuàng)建文本,有些通過(guò)展示循環(huán)和邏輯來(lái)控制流,有些引入額外的信息到模板中以供后續(xù)變量使用。

有些標(biāo)簽需要開(kāi)頭和結(jié)尾(比如:{% tag %}...標(biāo)簽內(nèi)容...{% endtag %})

Django大約有兩打(24個(gè))內(nèi)置模板標(biāo)簽。你可以查閱這篇文檔built-in tag reference.。以下僅列舉一些常用標(biāo)簽:

for

循環(huán)遍歷數(shù)組或列表,比如展示名為athete_list的運(yùn)動(dòng)員列表:

<ul>
{% for athlete in athlete_list %}
    <li>{{ athete.name }}</li>
{% endfor %}
</ul>

if,elif,else

{% if athlete_list %}
    Number of athletes: {{ athete_list|lengh }}
{% elif athlete_in_locker_room_list %}
    Athletes should be out of the locker room soon!
{% else %}
    No athletes.
{% endif %}

如上所示,如果athlete_list列表不為空,則會(huì)通過(guò){{ athlete_list|length }}變量來(lái)顯示列表長(zhǎng)度。否則,如果athlete_in_locker_room_list列表不為空,則顯示“Athletes should be out of the locker room soon!”信息。如果兩個(gè)列表都為空,則顯示“”No athletes.”。

你可以在if標(biāo)簽中使用過(guò)濾器以及進(jìn)行一系列的操作:

{% if athlete_list|length > 1 %}
   Team: {% for athlete in athlete_list %} ... {% endfor %}
{% else %}
   Athlete: {{ athlete_list.0.name }}
{% endif %}

當(dāng)上面的代碼運(yùn)行時(shí),注意大部分模板過(guò)濾器是以字符串類(lèi)型返回的,所以上面過(guò)濾器返回的length是無(wú)法與數(shù)字1進(jìn)行比較的。

block,extend

用于模板繼承(下面會(huì)講到),一種 給力的方法可以在模板中減少樣板的使用。

再說(shuō)下,上面僅是模板標(biāo)簽的一部分,查看更多內(nèi)容請(qǐng)移步至此built-intag reference

當(dāng)然你可以參考這篇文檔Custom template tags and filters來(lái)創(chuàng)建你自己的模板標(biāo)簽。

提示
Django 的admin交互界面使用了所有的模板標(biāo)簽和過(guò)濾器。你可以參考這篇文章The Django admin documentation generator.

注釋

可以用{# #}來(lái)注釋模板中的某一行。

如下,下面只有“hello”會(huì)在模板中起作用。

{# greeting #}hello

注釋中可以包含任何模板語(yǔ)句,如下:

{# {% if foo %}bar{% else %} #}

上述的注釋語(yǔ)句只能用于單行注釋({ # # }該注釋語(yǔ)句中不允許存在多行)。如果你想用多行注釋,請(qǐng)移步至此注釋

模板繼承

在Django模板引擎中最給力也是最復(fù)雜的部分就是模板繼承。模板繼承可以使你建立一個(gè)包含網(wǎng)站所有公共元素的基本骨架,在里面可以定義一些區(qū)塊,模板的子模板可以重寫(xiě)這些區(qū)塊。

下面的例子可以讓你更好的理解模板繼承:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %}My amazing site{% endblock %}</title>
</head>

<body>
    <div id="sidebar">
        {% block sidebar %}
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
        {% endblock %}
    </div>

    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

這個(gè)模板我們將它取名為base.html,定義了一個(gè)簡(jiǎn)單的HTML骨架文檔,在一個(gè)簡(jiǎn)單的兩列布局的頁(yè)面你也許會(huì)用到它。子模板要做的就是將內(nèi)容填充到空的區(qū)塊中。

在這個(gè)例子中,標(biāo)簽block定義了三個(gè)可以讓子模板重寫(xiě)的區(qū)塊。每個(gè)block標(biāo)簽都會(huì)告訴模板引擎,子模板可能會(huì)重寫(xiě)該區(qū)塊。

下面我們定義了一個(gè)子模板:

{% extends "base.html" %}

{% block title %}My amazing blog{% endblock %}

{% block content %}
{% for entry in blog_entries %}
    <h2>{{ entry.title }}</h2>
    <p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}

其中關(guān)鍵的地方是extends標(biāo)簽,這可以告訴模板引擎該模板是繼承于其他模板。這樣當(dāng)模板系統(tǒng)執(zhí)行該模板時(shí),就可以先定位他的父模板,上面模板的父模板就是“base.html”。

在該例中,模板引擎會(huì)注意到在base.html中有三個(gè)block標(biāo)簽,然后會(huì)將子模板的內(nèi)容填充到父模板相應(yīng)的區(qū)塊中。最后的結(jié)果如下({% block content %}區(qū)塊里具體的內(nèi)容是由blog_entries 變量決定的):

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>My amazing blog</title>
</head>

<body>
    <div id="sidebar">
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
    </div>

    <div id="content">
        <h2>Entry one</h2>
        <p>This is my first entry.</p>

        <h2>Entry two</h2>
        <p>This is my second entry.</p>
    </div>
</body>
</html>

注意到,我們沒(méi)有在子模板中定義sidebar區(qū)塊,但還是有內(nèi)容,沒(méi)錯(cuò)這是從父模板中來(lái)的。因此父模板的{%block%}標(biāo)簽中的內(nèi)容總是作為默認(rèn)值,,即假如子模板沒(méi)有重寫(xiě)該區(qū)塊,那么就默認(rèn)使用父模板中的內(nèi)容。

你可以根據(jù)需要采用多層繼承,一般來(lái)講我們采用的是三層繼承:

  • 首先創(chuàng)建一個(gè)包含網(wǎng)站主體外觀的基礎(chǔ)模板base.html
  • 為每部分的網(wǎng)頁(yè)創(chuàng)建名為base_部分名稱.html的模板,比如,base_news.html,base_sports.html。這些模板都是繼承base.html模板,并且都有自己的設(shè)計(jì)樣式。
  • 為每一種類(lèi)型的網(wǎng)頁(yè)創(chuàng)建個(gè)性化模板,比如新聞或者博客,它們都是繼承上述相應(yīng)的部分模板

上述的繼承方案可以極大化的重用你的代碼,并且方便擴(kuò)展。

以下是使用模板繼承需要注意的地方:

  • 如果你要在模板標(biāo)簽中使用{% extends %},那么它必須作為第一個(gè)模板標(biāo)簽,否則模板繼承將失效。
  • 在你的基礎(chǔ)模板中多使用{ % block % }。記住,在子模板中不一定都要重寫(xiě)父模板的block標(biāo)簽,所以你可以在父模板中多定義些block,在里面填充合理的默認(rèn)值,這樣在子模板中你可以根據(jù)需要重寫(xiě)相應(yīng)的block,其他的使用父模板的默認(rèn)值就可以了。俗話說(shuō),有備無(wú)患嗎。
  • 如果你發(fā)現(xiàn)在很多模板中有相同的內(nèi)容,那么你可以將這些相同的內(nèi)容提取出來(lái)放在父模板的block中。
  • 如果你想獲取父模板block中的內(nèi)容,你可以使用變量{{ block.super }}。如果你想要增加父模板block的內(nèi)容,而不是重寫(xiě)它,那么這個(gè)變量將會(huì)非常有用。使用該變量插入的數(shù)據(jù)不會(huì)被自動(dòng)轉(zhuǎn)義(下面會(huì)提到),因?yàn)槿绻斜匾脑捤呀?jīng)在父模板中被轉(zhuǎn)以了。
  • 在{ % block % }標(biāo)簽外面用as標(biāo)簽創(chuàng)建的變量是無(wú)法在{ % block % }內(nèi)部使用的,如下,該模板不會(huì)顯示任何內(nèi)容:
{% trans "Title" as title %}
{% block content %}{{ title }}{% endblock %}
  • 另外,你可以給 {% endblock %} 標(biāo)簽取任意名字,比如:
{% block content %}
...
{% endblock content %}

在很大的模板中,這可以讓你知道哪個(gè)block標(biāo)簽正在關(guān)閉。

最后,注意你不能在同一模板中定義相同名字的block標(biāo)簽,這是因?yàn)閎lock標(biāo)簽是雙向作用的,block標(biāo)簽不僅僅提供區(qū)域讓子模板填充,它也可以在父模板中填充相應(yīng)的內(nèi)容。如果在模板中有相同名字的block標(biāo)簽,那么,父模板將不知道到底使用哪個(gè)block中的內(nèi)容來(lái)填充。

HTML自動(dòng)轉(zhuǎn)義

當(dāng)通過(guò)模板生成HTML時(shí),有個(gè)風(fēng)險(xiǎn),就是變量中可能存在一些特殊字符會(huì)影響HTML的結(jié)果。比如,如下模板片段:

hello, {{ name }}

這從表面上看上去沒(méi)什么問(wèn)題,但是你需要考慮到,如果用戶的變量name輸入以下內(nèi)容會(huì)發(fā)生什么:

<script>alert('hello')</script>

如果name變量是以上內(nèi)容,那么最后HTML中會(huì)是這樣的結(jié)果:

Hello, <script>alert('hello')</script>

...這意味著瀏覽器會(huì)彈出一個(gè)腳本對(duì)話框!

類(lèi)似的,如果name變量包含‘<’字符呢,比如這樣:

<b>username

這會(huì)導(dǎo)致網(wǎng)頁(yè)的剩余部分加粗。

顯然,用戶提交的數(shù)據(jù)是不能盲目信任的,并且不能直接插入到網(wǎng)頁(yè)中,因?yàn)闀?huì)有惡意的用戶利用這種漏洞來(lái)干壞事。這種安全漏洞叫做跨站腳本攻擊(XSS)。

為了避免這個(gè)問(wèn)題,你有兩種選擇:

  • 一種,你可以利用escape過(guò)濾器來(lái)運(yùn)行每個(gè)不被信任的變量,這會(huì)把有潛在危險(xiǎn)的字符轉(zhuǎn)換為安全的。當(dāng)然在Django推出的頭幾年,這是一種默認(rèn)的解決方法。但是存在一個(gè)問(wèn)題,你需要確保每個(gè)變量都被轉(zhuǎn)義,顯然我們很容易漏掉一些數(shù)據(jù)。

  • 第二種,你可以利用Django的HTML自動(dòng)轉(zhuǎn)義機(jī)制。這部分的剩余部分會(huì)講解自動(dòng)轉(zhuǎn)義是如何工作的。

在Django中,每個(gè)模板都會(huì)默認(rèn)轉(zhuǎn)義每個(gè)變量,以下是五個(gè)比較特別的字符轉(zhuǎn)義。

  • < 會(huì)被轉(zhuǎn)義成<
  • > 會(huì)被轉(zhuǎn)義成>
  • '(單引號(hào))會(huì)被轉(zhuǎn)義成'
  • " (雙引號(hào))會(huì)被轉(zhuǎn)義成"
  • & 會(huì)被轉(zhuǎn)義成&

在強(qiáng)調(diào)一遍,這種自動(dòng)轉(zhuǎn)義行為是默認(rèn)的,當(dāng)你在使用Django的模板系統(tǒng)時(shí)你是受保護(hù)的。

如果關(guān)閉自動(dòng)轉(zhuǎn)義

如果你不想要數(shù)據(jù)被自動(dòng)轉(zhuǎn)義,比如你不想要某個(gè)網(wǎng)頁(yè),或者某個(gè)模板亦或者某個(gè)變量被轉(zhuǎn)義的話,你有幾個(gè)方法來(lái)關(guān)閉它。

為什么你會(huì)想關(guān)閉自動(dòng)轉(zhuǎn)義呢?因?yàn)橛袝r(shí)候你想把原生的HTML語(yǔ)句嵌入到模板變量中,在這種情況下,你是不會(huì)想要將變量里的內(nèi)容轉(zhuǎn)義的。舉個(gè)例子,你可能在數(shù)據(jù)庫(kù)中存了一點(diǎn)HTML,你想把它直接嵌入到模板中?;蛘?,你可能正在用Django的模板系統(tǒng)生成非HTML文本,比如電子郵箱信息。

關(guān)閉變量的自動(dòng)轉(zhuǎn)義

可以用safe過(guò)濾器來(lái)關(guān)閉單個(gè)變量的自動(dòng)轉(zhuǎn)義:

這會(huì)被轉(zhuǎn)義: {{ data }}
這不會(huì)被轉(zhuǎn)義: {{ data|safe }}

如果data變量中存在<b>,那么上面兩句輸出的結(jié)果是這樣的:

這會(huì)被轉(zhuǎn)義: <b>
這不會(huì)被轉(zhuǎn)義: <b>

關(guān)閉模板區(qū)塊的自動(dòng)轉(zhuǎn)義

為了控制模板的自動(dòng)轉(zhuǎn)義,需要在外面套一層autoescape標(biāo)簽,比如:

{% autoescape off %}
    Hello {{ name }}
{% endautoescape %}

你可以用on或者off來(lái)控制是否自動(dòng)轉(zhuǎn)義,如下例子:

Auto-escaping is on by default. Hello {{ name }}

{% autoescape off %}
    This will not be auto-escaped: {{ data }}.

    Nor this: {{ other_data }}
    {% autoescape on %}
        Auto-escaping applies again: {{ name }}
    {% endautoescape %}
{% endautoescape %}

自動(dòng)轉(zhuǎn)義標(biāo)簽會(huì)通過(guò)繼承來(lái)傳遞它的影響,包括include標(biāo)簽。舉例:

以下是base.html

{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}

以下是child.html

{% extends "base.html" %}
{% block title %}This & that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}

由于在base.html中自動(dòng)轉(zhuǎn)義是關(guān)閉的,在他的子模板child.html中也將是關(guān)閉的。如果greeting變量傳入字符串<b>Hello!</b>,那么模板最終的結(jié)果將會(huì)是如下:

<h1>This & that</h1>
<b>Hello!</b>

注意事項(xiàng)

通常來(lái)講,我們不用過(guò)多的擔(dān)心自動(dòng)轉(zhuǎn)義。只有在寫(xiě)views時(shí)或者自定義過(guò)濾器時(shí)需要注意自動(dòng)轉(zhuǎn)義,并合理的標(biāo)記數(shù)據(jù)。所以盡情的使用模板吧。

如果你創(chuàng)建的模板在被使用時(shí)無(wú)法確定自動(dòng)轉(zhuǎn)義是否打開(kāi),你可以添加escape過(guò)濾器到每個(gè)需要轉(zhuǎn)義的變量上。當(dāng)自動(dòng)轉(zhuǎn)義已開(kāi)啟,escape過(guò)濾器對(duì)已轉(zhuǎn)義的變量進(jìn)行再次轉(zhuǎn)義并不會(huì)對(duì)該變量產(chǎn)生影響。

字符串與自動(dòng)轉(zhuǎn)義

在前面提到,過(guò)濾器的參數(shù)可以是字符串:

{{ data|default:"This is a string literal." }}

所有在模板中的字面上的字符串都不會(huì)經(jīng)過(guò)轉(zhuǎn)義--他們看上去像使用了safe過(guò)濾器。這背后的原因是字符串內(nèi)容是由模板創(chuàng)建者決定的,所以他們可以確保文本是被正確轉(zhuǎn)義的。

也就是說(shuō)你應(yīng)該這樣寫(xiě):

{{ data|default:"3 < 2" }}

而不是這樣:

{{ data|default:"3 < 2" }}  {# 別這樣寫(xiě)! #}

這不會(huì)影響變量data自身,變量的內(nèi)容在必要時(shí)仍然會(huì)被自動(dòng)轉(zhuǎn)義,因?yàn)檫@不是模板作者能控制的。

訪問(wèn)方法調(diào)用

大多數(shù)綁定在對(duì)象上的方法調(diào)用也存在于模板中。這意味著模板可以訪問(wèn)的不僅僅是類(lèi)的屬性以及從view中傳來(lái)的變量。舉個(gè)例子,Django的ORM(對(duì)象關(guān)系映射)框架提供個(gè)一個(gè)叫“entry_set”語(yǔ)法,這可以找到由外鍵關(guān)聯(lián)的對(duì)象集。所以如果模型“comment”有個(gè)外鍵關(guān)聯(lián)到模型“task”的話,你可以遍歷該task的所有comments:

{% for comment in task.comment_set.all %}
    {{ comment }}
{% endfor %}

類(lèi)似的,QuerySets提供了一個(gè)叫count()的方法用來(lái)計(jì)算所包含對(duì)象的總個(gè)數(shù)。因此你可以得到關(guān)聯(lián)到task上的comment總和:

{{ task.comment_set.all.count }}

當(dāng)然你可以輕松的訪問(wèn)你之前已經(jīng)定義過(guò)的模型中的方法:

models.py:

class Task(models.Model):
    def foo(self):
        return "bar"

template.html:

{{ task.foo }}

由于Django有意限制了模板語(yǔ)言中的邏輯處理,你不可以在方法中傳遞參數(shù),數(shù)據(jù)應(yīng)該在view處理,再傳入模板中展示。

自定義標(biāo)簽和過(guò)濾器庫(kù)

一些應(yīng)用提供了自定義標(biāo)簽和過(guò)濾器的庫(kù),要想在模板中使用,請(qǐng)確保該應(yīng)用在INSTALLED_APPS(這里我添加了'django.contrib.humanize'庫(kù)),然后用load標(biāo)簽來(lái)加載:

{% load humanize %}

{{ 45000|intcomma }}

在上面例子中,我們用load標(biāo)簽來(lái)加載humanize標(biāo)簽庫(kù),這樣我們就可以使用該庫(kù)中的intcomma過(guò)濾器了。如果你開(kāi)啟了django.contrib.admindocs,你可以在admin站查詢文檔然后找出你安裝的自定義庫(kù)列表。

load標(biāo)簽后面可以跟多個(gè)庫(kù)名,當(dāng)中用空格隔開(kāi):

{% load humanize i18n %}

查看Custom template tags and filters文章來(lái)獲取更多關(guān)于自定義模板庫(kù)的信息。

自定義庫(kù)與模板繼承

當(dāng)你加載自定義標(biāo)簽或過(guò)濾器庫(kù)時(shí),這個(gè)庫(kù)中的標(biāo)簽以及過(guò)濾器只能在當(dāng)前模板使用,在其父模板或子模板是不起作用的。

比如,有一個(gè)模板foo.html寫(xiě)了{% load humanize %},其子模板中寫(xiě)了{ % extends “foo.html” %},但子模板還是無(wú)法訪問(wèn)父模板中humanize庫(kù)中的標(biāo)簽和過(guò)濾器的,要想訪問(wèn)就必須在子模板中再次添加{% load humanize %}。

這樣的特性主要是為了項(xiàng)目的維護(hù)性和邏輯性。

擴(kuò)展
模板參考
含內(nèi)置標(biāo)簽,內(nèi)置過(guò)濾器,使用其他模板,語(yǔ)言,以及更多其他內(nèi)容

官方原文:https://docs.djangoproject.com/en/1.11/ref/templates/language/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容