聲明:轉(zhuǎn)載請注明出處http://www.reibang.com/p/1664dcfd840c
最近在折騰Django,看到官網(wǎng)的Django模板文章寫得挺詳細(xì)的,就想著翻譯下以加深自己的學(xué)習(xí)印象度帮,如果能幫助到大家我也會(huì)感到很欣慰,以下是譯文。
這篇文章主要講解了Django模板系統(tǒng)語法,如果你想了解更多關(guān)于Django模板如何工作以及如何擴(kuò)展的話痹栖,可以看這篇文章The Django template language: for Python programmers.
Django 模板語言意在強(qiáng)大和輕松之間取得平衡。這讓那些習(xí)慣用HTML的人感到很舒服瞭空。如果你有接觸過任何其他的基于文本的模板語言揪阿,比如 Smarty 或者 Jinja2,那么你應(yīng)該對Django的模板語言倍感親切疗我。
注意:
如果你有編程背景,或者習(xí)慣于那些混合代碼直接嵌入到HTML中的語言南捂,你要記住Django模板系統(tǒng)不是將Python簡單的嵌入HTML中吴裤。這是它設(shè)計(jì)的初衷:模板系統(tǒng)主要為了表達(dá)而不是程序邏輯。Django模板系統(tǒng)提供了很多標(biāo)簽溺健,他們的方法很像一些程序結(jié)構(gòu)--if標(biāo)簽用于布爾判斷麦牺,for標(biāo)簽用于循環(huán)等等。但是這些不是簡單的作為相應(yīng)的Python代碼執(zhí)行矿瘦,模板系統(tǒng)不會(huì)執(zhí)行任意Python表達(dá)式枕面。只有下面列出的標(biāo)簽,過濾器缚去,以及語句是默認(rèn)支持的(但是你可以添加自定義模板標(biāo)簽和過濾器到模板語言如果有需要的話)
模板
模板就是一個(gè)簡單的文本文件,它可以生成任何文本格式(HTML,XML,CSV等)琼开。
模板中包含變量和標(biāo)簽易结,當(dāng)模板被執(zhí)行時(shí),變量會(huì)被賦值柜候,而標(biāo)簽是控制模板的邏輯的搞动。
下面是個(gè)演示了一些基礎(chǔ)知識的最小模板,稍后會(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的模板語言用在更多的地方而不是僅僅在XML或HTML中。在聯(lián)網(wǎng)的世界里辅柴,我們把它用在電子郵箱箩溃,JavaScript以及CSV。你可以在任何文本格式中使用模板語言碌嘀。哦涣旨,順便說下,讓人們編輯XML文件是很苦逼的股冗。
變量
變量看起來像這樣:{{ 變量名 }}
霹陡,當(dāng)模板引擎遇到變量時(shí),會(huì)計(jì)算這個(gè)變量止状,并把結(jié)果賦值給它烹棉。變量名是由任何的數(shù)字,字母以及下劃線組成怯疤。點(diǎn)(“.”)也會(huì)出現(xiàn)在變量部分浆洗,當(dāng)然他有特殊用途,稍后會(huì)說明旅薄。特別注意的是辅髓,變量名中不能出現(xiàn)空格符以及任何的標(biāo)點(diǎn)符號泣崩。
上面說到點(diǎn)也會(huì)出現(xiàn)在變量部分,它的作用就是用來訪問變量的屬性的洛口。
背景:
嚴(yán)格來講矫付,當(dāng)模板系統(tǒng)遇到點(diǎn)時(shí),它會(huì)根據(jù)以下的順序查找:
- 字典查找
- 屬性或方法查找
- 數(shù)字索引查找
如果結(jié)果的值是可調(diào)用第焰,那么它就會(huì)被無參數(shù)調(diào)用买优。調(diào)用的結(jié)果就會(huì)變成模板中的值。
這個(gè)查找順序會(huì)對那些覆寫了字典查找的對象造成一些不可預(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對象的title屬性代替砌左。
如果你調(diào)用的變量不存在,那么模板系統(tǒng)將默認(rèn)插入空字符串‘’
注意:如果模板的上下文(context)中傳入“bar”變量铺敌,而模板中存在{{ foo.bar }}表達(dá)式汇歹,那么該表達(dá)式僅僅具有字面意思,即調(diào)用foo的bar屬性偿凭,而不會(huì)調(diào)用context中“bar”的值产弹。
過濾器(FIlters)
你可以用filters
來改變變量最終顯示的值。
過濾器看起來就像這樣{{ name|lower }}弯囊。這是將name變量通過lower
過濾器全部轉(zhuǎn)換為小寫字母痰哨。|
用來調(diào)用過濾器。
過濾器可以是鏈?zhǔn)降某V浚粋€(gè)過濾器的輸出會(huì)被用在下一個(gè)作谭。{{ text|escape|linebreaks }} 是一種通用的形式用來將文本內(nèi)容轉(zhuǎn)義,然后再轉(zhuǎn)為<P>標(biāo)簽以適用HTML奄毡。
有些過濾器帶參數(shù)折欠。如以下帶參過濾器:{{ bio|truncatewords:30 }}意思是只展示bio變量的前30個(gè)字符。
如果過濾器參數(shù)含有空格那么參數(shù)必須被引號引起來吼过;比如想要用逗號和空格將list中的元素拼接起來锐秦,你可以這樣{{ list|join:“, ”}}盗忱。
Django提供了大約60個(gè)內(nèi)置模板過濾器酱床。你可以到built-in filter reference.查閱更多的過濾器。為了讓你嘗試下趟佃,下面是一些常用的過濾器:
default
如果一個(gè)變量是false或者是空的扇谣,那么它的值就是你給的默認(rèn)值昧捷,否則就是變量本身的值。比如:
{{ value|default:"nothing" }}
如果變量value沒有提供罐寨,或者是空的話靡挥,上面就會(huì)顯示nothing
。
length
返回變量的長度鸯绿。這對于字符串和列表都起作用跋破。比如:
{{ 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)建自定義模板過濾器,可以查閱這篇文章Custom template tags and filters.
提示
Django 的admin交互界面使用了所有的模板標(biāo)簽和過濾器蝎宇。你可以參考這篇文章The Django admin documentation generator.
標(biāo)簽(Tags)
標(biāo)簽的形式是 {% tag %}。標(biāo)簽比變量要更復(fù)雜:有些標(biāo)簽在輸出中創(chuàng)建文本祷安,有些通過展示循環(huán)和邏輯來控制流姥芥,有些引入額外的信息到模板中以供后續(xù)變量使用。
有些標(biāo)簽需要開頭和結(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ì)通過{{ athlete_list|length }}變量來顯示列表長度。否則读整,如果athlete_in_locker_room_list列表不為空簿训,則顯示“Athletes should be out of the locker room soon!”信息。如果兩個(gè)列表都為空米间,則顯示“”No athletes.”强品。
你可以在if標(biāo)簽中使用過濾器以及進(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í),注意大部分模板過濾器是以字符串類型返回的屈糊,所以上面過濾器返回的length是無法與數(shù)字1進(jìn)行比較的的榛。
block,extend
用于模板繼承(下面會(huì)講到)逻锐,一種 給力的方法可以在模板中減少樣板的使用夫晌。
再說下雕薪,上面僅是模板標(biāo)簽的一部分,查看更多內(nèi)容請移步至此built-intag reference
當(dāng)然你可以參考這篇文檔Custom template tags and filters來創(chuàng)建你自己的模板標(biāo)簽晓淀。
提示
Django 的admin交互界面使用了所有的模板標(biāo)簽和過濾器所袁。你可以參考這篇文章The Django admin documentation generator.
注釋
可以用{# #}
來注釋模板中的某一行。
如下要糊,下面只有“hello”會(huì)在模板中起作用纲熏。
{# greeting #}hello
注釋中可以包含任何模板語句,如下:
{# {% if foo %}bar{% else %} #}
上述的注釋語句只能用于單行注釋({ # # }該注釋語句中不允許存在多行)锄俄。如果你想用多行注釋局劲,請移步至此注釋
模板繼承
在Django模板引擎中最給力也是最復(fù)雜的部分就是模板繼承。模板繼承可以使你建立一個(gè)包含網(wǎng)站所有公共元素的基本骨架奶赠,在里面可以定義一些區(qū)塊鱼填,模板的子模板可以重寫這些區(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è)簡單的HTML骨架文檔苹丸,在一個(gè)簡單的兩列布局的頁面你也許會(huì)用到它。子模板要做的就是將內(nèi)容填充到空的區(qū)塊中苇经。
在這個(gè)例子中赘理,標(biāo)簽block定義了三個(gè)可以讓子模板重寫的區(qū)塊。每個(gè)block標(biāo)簽都會(huì)告訴模板引擎扇单,子模板可能會(huì)重寫該區(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>
注意到银受,我們沒有在子模板中定義sidebar區(qū)塊,但還是有內(nèi)容慎王,沒錯(cuò)這是從父模板中來的蚓土。因此父模板的{%block%}標(biāo)簽中的內(nèi)容總是作為默認(rèn)值,赖淤,即假如子模板沒有重寫該區(qū)塊蜀漆,那么就默認(rèn)使用父模板中的內(nèi)容。
你可以根據(jù)需要采用多層繼承咱旱,一般來講我們采用的是三層繼承:
- 首先創(chuàng)建一個(gè)包含網(wǎng)站主體外觀的基礎(chǔ)模板
base.html
- 為每部分的網(wǎng)頁創(chuàng)建名為
base_部分名稱.html
的模板确丢,比如绷耍,base_news.html,base_sports.html鲜侥。這些模板都是繼承base.html模板褂始,并且都有自己的設(shè)計(jì)樣式。 - 為每一種類型的網(wǎng)頁創(chuàng)建個(gè)性化模板描函,比如新聞或者博客崎苗,它們都是繼承上述相應(yīng)的部分模板
上述的繼承方案可以極大化的重用你的代碼,并且方便擴(kuò)展舀寓。
以下是使用模板繼承需要注意的地方:
- 如果你要在模板標(biāo)簽中使用
{% extends %}
,那么它必須作為第一個(gè)模板標(biāo)簽胆数,否則模板繼承將失效。 - 在你的基礎(chǔ)模板中多使用
{ % block % }
互墓。記住必尼,在子模板中不一定都要重寫父模板的block標(biāo)簽,所以你可以在父模板中多定義些block篡撵,在里面填充合理的默認(rèn)值判莉,這樣在子模板中你可以根據(jù)需要重寫相應(yīng)的block,其他的使用父模板的默認(rèn)值就可以了育谬。俗話說券盅,有備無患嗎。 - 如果你發(fā)現(xiàn)在很多模板中有相同的內(nèi)容膛檀,那么你可以將這些相同的內(nèi)容提取出來放在父模板的block中渗饮。
- 如果你想獲取父模板block中的內(nèi)容,你可以使用變量{{ block.super }}宿刮。如果你想要增加父模板block的內(nèi)容,而不是重寫它私蕾,那么這個(gè)變量將會(huì)非常有用僵缺。使用該變量插入的數(shù)據(jù)不會(huì)被自動(dòng)轉(zhuǎn)義(下面會(huì)提到),因?yàn)槿绻斜匾脑捤呀?jīng)在父模板中被轉(zhuǎn)以了踩叭。
- 在{ % block % }標(biāo)簽外面用
as
標(biāo)簽創(chuàng)建的變量是無法在{ % 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)容來填充刻帚。
HTML自動(dòng)轉(zhuǎn)義
當(dāng)通過模板生成HTML時(shí),有個(gè)風(fēng)險(xiǎn)涩嚣,就是變量中可能存在一些特殊字符會(huì)影響HTML的結(jié)果崇众。比如,如下模板片段:
hello, {{ name }}
這從表面上看上去沒什么問題航厚,但是你需要考慮到顷歌,如果用戶的變量name輸入以下內(nèi)容會(huì)發(fā)生什么:
<script>alert('hello')</script>
如果name變量是以上內(nèi)容,那么最后HTML中會(huì)是這樣的結(jié)果:
Hello, <script>alert('hello')</script>
...這意味著瀏覽器會(huì)彈出一個(gè)腳本對話框阶淘!
類似的衙吩,如果name變量包含‘<’字符呢,比如這樣:
<b>username
這會(huì)導(dǎo)致網(wǎng)頁的剩余部分加粗溪窒。
顯然坤塞,用戶提交的數(shù)據(jù)是不能盲目信任的,并且不能直接插入到網(wǎng)頁中澈蚌,因?yàn)闀?huì)有惡意的用戶利用這種漏洞來干壞事摹芙。這種安全漏洞叫做跨站腳本攻擊(XSS)。
為了避免這個(gè)問題宛瞄,你有兩種選擇:
一種浮禾,你可以利用
escape
過濾器來運(yùn)行每個(gè)不被信任的變量,這會(huì)把有潛在危險(xiǎn)的字符轉(zhuǎn)換為安全的份汗。當(dāng)然在Django推出的頭幾年盈电,這是一種默認(rèn)的解決方法。但是存在一個(gè)問題杯活,你需要確保每個(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)義成>
-
'
(單引號)會(huì)被轉(zhuǎn)義成'
-
"
(雙引號)會(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)頁车遂,或者某個(gè)模板亦或者某個(gè)變量被轉(zhuǎn)義的話封断,你有幾個(gè)方法來關(guān)閉它。
為什么你會(huì)想關(guān)閉自動(dòng)轉(zhuǎn)義呢舶担?因?yàn)橛袝r(shí)候你想把原生的HTML語句嵌入到模板變量中坡疼,在這種情況下,你是不會(huì)想要將變量里的內(nèi)容轉(zhuǎn)義的衣陶。舉個(gè)例子柄瑰,你可能在數(shù)據(jù)庫中存了一點(diǎn)HTML,你想把它直接嵌入到模板中剪况〗陶矗或者,你可能正在用Django的模板系統(tǒng)生成非HTML文本译断,比如電子郵箱信息授翻。
關(guān)閉變量的自動(dòng)轉(zhuǎn)義
可以用safe
過濾器來關(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來控制是否自動(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ì)通過繼承來傳遞它的影響翎蹈,包括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)
通常來講,我們不用過多的擔(dān)心自動(dòng)轉(zhuǎn)義澄阳。只有在寫views時(shí)或者自定義過濾器時(shí)需要注意自動(dòng)轉(zhuǎn)義拥知,并合理的標(biāo)記數(shù)據(jù)。所以盡情的使用模板吧碎赢。
如果你創(chuàng)建的模板在被使用時(shí)無法確定自動(dòng)轉(zhuǎn)義是否打開举庶,你可以添加escape
過濾器到每個(gè)需要轉(zhuǎn)義的變量上。當(dāng)自動(dòng)轉(zhuǎn)義已開啟揩抡,escape
過濾器對已轉(zhuǎn)義的變量進(jìn)行再次轉(zhuǎn)義并不會(huì)對該變量產(chǎn)生影響。
字符串與自動(dòng)轉(zhuǎn)義
在前面提到镀琉,過濾器的參數(shù)可以是字符串:
{{ data|default:"This is a string literal." }}
所有在模板中的字面上的字符串都不會(huì)經(jīng)過轉(zhuǎn)義--他們看上去像使用了safe過濾器峦嗤。這背后的原因是字符串內(nèi)容是由模板創(chuàng)建者決定的,所以他們可以確保文本是被正確轉(zhuǎn)義的屋摔。
也就是說你應(yīng)該這樣寫:
{{ data|default:"3 < 2" }}
而不是這樣:
{{ data|default:"3 < 2" }} {# 別這樣寫烁设! #}
這不會(huì)影響變量data自身,變量的內(nèi)容在必要時(shí)仍然會(huì)被自動(dòng)轉(zhuǎn)義,因?yàn)檫@不是模板作者能控制的装黑。
訪問方法調(diào)用
大多數(shù)綁定在對象上的方法調(diào)用也存在于模板中副瀑。這意味著模板可以訪問的不僅僅是類的屬性以及從view中傳來的變量。舉個(gè)例子恋谭,Django的ORM(對象關(guān)系映射)框架提供個(gè)一個(gè)叫“entry_set”語法糠睡,這可以找到由外鍵關(guān)聯(lián)的對象集。所以如果模型“comment”有個(gè)外鍵關(guān)聯(lián)到模型“task”的話疚颊,你可以遍歷該task的所有comments:
{% for comment in task.comment_set.all %}
{{ comment }}
{% endfor %}
類似的狈孔,QuerySets提供了一個(gè)叫count()
的方法用來計(jì)算所包含對象的總個(gè)數(shù)。因此你可以得到關(guān)聯(lián)到task上的comment總和:
{{ task.comment_set.all.count }}
當(dāng)然你可以輕松的訪問你之前已經(jīng)定義過的模型中的方法:
models.py:
class Task(models.Model):
def foo(self):
return "bar"
template.html:
{{ task.foo }}
由于Django有意限制了模板語言中的邏輯處理材义,你不可以在方法中傳遞參數(shù)均抽,數(shù)據(jù)應(yīng)該在view處理,再傳入模板中展示其掂。
自定義標(biāo)簽和過濾器庫
一些應(yīng)用提供了自定義標(biāo)簽和過濾器的庫油挥,要想在模板中使用,請確保該應(yīng)用在INSTALLED_APPS
(這里我添加了'django.contrib.humanize'庫)款熬,然后用load
標(biāo)簽來加載:
{% load humanize %}
{{ 45000|intcomma }}
在上面例子中深寥,我們用load標(biāo)簽來加載humanize標(biāo)簽庫,這樣我們就可以使用該庫中的intcomma
過濾器了华烟。如果你開啟了django.contrib.admindocs,你可以在admin站查詢文檔然后找出你安裝的自定義庫列表翩迈。
load
標(biāo)簽后面可以跟多個(gè)庫名,當(dāng)中用空格隔開:
{% load humanize i18n %}
查看Custom template tags and filters文章來獲取更多關(guān)于自定義模板庫的信息盔夜。
自定義庫與模板繼承
當(dāng)你加載自定義標(biāo)簽或過濾器庫時(shí)负饲,這個(gè)庫中的標(biāo)簽以及過濾器只能在當(dāng)前模板使用,在其父模板或子模板是不起作用的喂链。
比如返十,有一個(gè)模板foo.html
寫了{% load humanize %}
,其子模板中寫了{ % extends “foo.html” %}
椭微,但子模板還是無法訪問父模板中humanize庫中的標(biāo)簽和過濾器的洞坑,要想訪問就必須在子模板中再次添加{% load humanize %}
。
這樣的特性主要是為了項(xiàng)目的維護(hù)性和邏輯性蝇率。
擴(kuò)展
模板參考
含內(nèi)置標(biāo)簽迟杂,內(nèi)置過濾器,使用其他模板本慕,語言排拷,以及更多其他內(nèi)容
官方原文:https://docs.djangoproject.com/en/1.11/ref/templates/language/