---恢復內容開始---
1. 常用語法
需要記住兩組特殊符號:{{ }} 和 {% %}。
在運用到變量的時候使用{{ }},如果是跟邏輯相關的話就使用{% %}。
在Django模板(template)中,會使用到的{{ }} 和 {% %}寫法,在專業中就稱之為Django的 “ 模板語言 ”
2. 變量
在Django模板中,使用的變量的時候,就是用這個格式:{{ 變量名 }}。
在template模板引擎遇到一個變量的時候,它自動根據python后台中的views模塊提供的相關數據,計算出這個變量的結果,並用這個結果替換掉它自己。
變量命名:命名規則包含(字符、數字、下划線)的組合。
注意:變量的名稱一定不能含有空格、標點符號。
點(.)在模板語言中有特殊的含義。當模版系統遇到點("."),它將以這樣的查詢優先級:
第一:字典查詢(Dictionary lookup)
第二:屬性或方法查詢(Attribute or method lookup)
第三:數字索引查詢(Numeric index lookup)
注意事項:
- 如果計算結果的值是可調用的,它將被無參數的調用。 調用的結果將成為模版的值。
- 如果使用的變量不存在, 模版系統將插入 string_if_invalid 選項的值, 它被默認設置為'' (空字符串) 。
變量的使用寫法:
{# 取list列表中的第一個參數 #} {{ list.0 }} {# 取d字典中key的值 #} {{ d.name }} {# 取對象的name屬性 #} {{ person_list.0.name }} {# (大白話:人對象的列表 的 第一個人對象 的 名字)," . "點跟"的”有些類似#}
{# .操作只能調用不帶參數的方法 #} {{ person_list.0.eat }}
注意:如果是調用方法的話,后面也不能帶括號()。
3. Filters(過濾器)
在Django的模板語言中,通過使用過濾器來改變變量的顯示(結果)。
過濾器的語法:{{ name|filter_name:參數 }}。注意:使用管道符 ” | “ 。name就是變量的結果,其實就是變量名。
例如:在模板中的一個變量使用如下{{ name|lower}}會將name變量通過length過濾(操作)之后再顯示它的值。lower在這里的作用是將文本全都變成小寫。
注意事項:
- 過濾器支持“鏈式”操作。即一個過濾器的輸出作為另一個過濾器的輸入 。
- 過濾器可以接受參數。例如:{{ sss|truncatewords:30 }},這將顯示sss的前30個詞。
- 過濾器參數包含空格的話,必須用引號包裹起來。比如使用逗號和空格去連接一個列表中的元素,如:{{ list|join:', ' }}
- '|'左右沒有空格沒有空格沒有空格
3.1 default
例如:{{ name|default:"not found" }}
如果變量name的值是false或者為空或者不存在,該處自動被默認值not found字符串代替,或者說此處的變量名的值自動為"not found" 。
3.2 length
例如:{{ name|length}}
返回變量name的值的長度,作用於字符串和列表。
如果上面的name=[1, 2, 3, 4, 5, 6],那上面得到的值就是6.
3.3 filesizeformat
例如:{{ name|filesizeformat }}
將name的值進行格式化,也就是說,將一個文件的大小進行自動轉換成為,我們平時生活中能夠理解的格式!(例如:“ 20MB ”,“ 20KB ”,“ 20GB ” 等等)
如果name的值是123456789,輸出的將會是117.7MB。
3.4 slice
例如:{{ name_list|slice:":2" }
返回列表的一部分。也就是切片,與Python的列表切片相同的語法。
如果name_list = ["張三", "李四", "王五", "老六"],那上面的結果將會得到["張三", "李四"]
3.5 date
根據給定格式對一個日期變量進行格式化。
可用的格式字符串:
格式化字符 | 描述 | 示例輸出 |
---|---|---|
a | 'a.m.'或'p.m.' | 'a.m.' |
A | 'AM'或'PM' | 'AM' |
b | 月份,文字形式,3個字母,小寫。 | “jan” |
B | 未實現。 | |
c | ISO 8601格式 | 2008-01-02T10:30:00.000123+02:00 |
d | 月的日子,帶前導零的2位數字。 | '01'到'31' |
D | 周幾的文字表述形式,3個字母。 | 'Fri' |
e | 時區名稱 | '','GMT','-500','US/Eastern'等 |
E | 月份,分地區。 | |
f | 時間 | '1','1:30' |
F | 月,文字形式。 | 'January' |
g | 12小時格式,無前導零。 | '1'到'12' |
G | 24小時格式,無前導零。 | '0'到'23' |
h | 12小時格式。 | '01'到'12' |
H | 24小時格式。 | '00'到'23' |
i | 分鍾 | '00'到'59' |
I | 夏令時間,無論是否生效。 | '1'或'0' |
j | 沒有前導零的月份的日子。 | '1'到'31' |
l | 星期幾,完整英文名 | 'Friday' |
L | 布爾值是否是一個閏年。 | True或False |
m | 月,2位數字帶前導零。 | '01'到'12' |
M | 月,文字,3個字母。 | “Jan” |
n | 月無前導零。 | '1'到'12' |
N | 美聯社風格的月份縮寫。 | 'Jan.','Feb.','March','May' |
o | ISO-8601周編號 | '1999' |
O | 與格林威治時間的差,單位小時。 | '+0200' |
P | 時間為12小時 | '1 am','1:30 pm','midnight','noon','12:30 pm'> |
r | RFC 5322格式化日期。 | 'Thu, 21 Dec 2000 16:01:07 +0200' |
s | 秒,帶前導零的2位數字。 | '00'到'59' |
S | 一個月的英文序數后綴,2個字符。 | 'st','nd','rd'或'th' |
t | 給定月份的天數。 | 28 to 31 |
T | 本機的時區。 | 'EST','MDT' |
u | 微秒。 | 000000 to 999999 |
U | 自Unix Epoch以來的秒數(1970年1月1日00:00:00 UTC)。 | |
w | 星期幾,數字無前導零。 | '0'(星期日)至'6'(星期六) |
W | ISO-8601周數,周數從星期一開始。 | 1,53 |
y | 年份,2位數字。 | '99' |
Y | 年,4位數。 | '1999' |
z | 一年中的日子 | 0到365 |
Z | 時區偏移量,單位為秒。 | -43200到43200 |
例如:{{ name|date:"Y-m-d H:i:s"}}
如果name是一個datetime對象,比如datetime.datetime.now(),輸出將是字符串 ' 2017-08-30 11:08:29 ' 。
可以將date與time過濾器結合使用,以呈現datetime值的完整表示形式。 例如:
{{ value|date:"D d M Y" }} {{ value|time:"H:i" }}
3.6 safe
例如:
{{ name|safe }}
將字符串標記為安全,不需要轉義。
詳解:
Django的模板中會對HTML標簽和JS等語法標簽進行自動轉義,原因顯而易見,這樣是為了安全。但是有的時候我們可能不希望這些HTML元素被轉義,比如我們做一個內容管理系統,后台添加的文章中是經過修飾的,這些修飾可能是通過一個類似於FCKeditor編輯加注了HTML修飾符的文本,如果自動轉義的話顯示的就是保護HTML標簽的源文件。為了在Django中關閉HTML的自動轉義有兩種方式,如果是一個單獨的變量我們可以通過過濾器“|safe”的方式告訴Django這段代碼是安全的不i必轉義。
如果這里的name的值為name= "<a href='http://www.baidu.com/'>點我進入百度</a>"。這個時候,這里的點我將會成為一個定向百度鏈接的超級鏈接,也就是說只要點擊" 點我進入百度 "就可以跳轉到百度頁面!
3.7 truncatechars
例如:
{{ name|truncatechars:9 }}
參數:截斷之后剩下的字符數
如果字符串包含的字符總個數多於指定的字符數量,那么會被截斷掉后面的部分。截斷的字符串將以“...”結尾,注意結尾中的 ”...“ 算三個字符 。
如果這里的name的值是 “my name is xxxx”,那上面輸出的結果是:my nam...
3.8 truncatewords
例如:
{{ name|truncatewords:2 }}
在一定數量的字數后截斷字符串。與truncatechars不同的是,這個以字的個數計數,而不是字符計數。截斷的字符串將以“...”結尾,注意結尾中的 ”...“ 在這里不算三個字符了 。
如果這里的name的值還是“my name is xxxx” ,那上面輸出的結果是:my name...
3.9 cut
例如:
{{ name|cut:"," }}
移除name中所有的與給定參數相同的字符串。這里的是意思是:移除name的值中,存在的逗號 ”,"。
如果name的值是為“my,name,is,xxxx”,輸出將為"Smynameisxxxx"。
3.10 join
例如:{{ name|join:"//" }}
使用字符串連接列表,類似Python的str.join(list)
如果上面的name=["aa", "bb", "cc"],在帶入上面變量之后得到的結果就是:aa//bb//cc。
注意:如果name是字典的話,例如:name={"aaa": 111, "bbb": 222},結果為key的鏈接,即得到的結果為:aaa//bbb
3.11 timesince
傳入的時間對象(blog_date)跟當前的時刻的時間(comment_date)的一個時間差,用於寫多長時間之前。說白了,這個就是計算兩個時間的時間差(comment_date — blog_date)。
時間的差值被Django自動換算,可以表示(例如,“4天,6小時”)。
例如:{{ blog_date|timesince:comment_date }}
3.12 timeuntil
類似於timesince,它測量從現在開始直到給定日期或日期時間的時間。例如,如果今天是2006年6月1日,而conference_date
是2006年6月29日,則{{ conference_date | timeuntil }}
將返回“4 weeks”。
可選參數是一個包含用作比較點的日期變量。如果from_date
為2006年6月22日,則以下內容將返回“1 weeks”:
{{ conference_date|timeuntil:from_date }}
3.13 自定義filter
自定義的filter(過濾器)可以分為三大步驟:首先是前期步驟,然后是編輯filter過濾器,最后是使用自定義filter過濾器
首先,自定義filter前期步驟:
1. 在app中新建一個templatetags
包(名字固定,不能變,只能是這個),和views.py、models.py等文件處於同一級別目錄下。這是一個python包!所以,一定不要忘記這個包的里面是要有__init__.py
文件的,因為__init__.py文件是以使得該目錄可以作為Python的包的條件。
2. 在添加templatetags包后,需要重新啟動項目,然后才能在模板中使用標簽或過濾器。
3. 在templatetages包里,創建自定義過濾器的模塊。
a 將你自定義的標簽和過濾器將放在templatetags包下的一個模塊里。
b 這個模塊的名字是后面載入標簽時使用的標簽名,所以要謹慎的選擇名字以防與其他應用下的自定義標簽和過濾器名字沖突,當然更不能與Django內置的沖突。
假設你自定義的標簽/過濾器在一個名為app01_myfilter.py
的文件中,那么你的app目錄結構看起來應該是這樣的:
app01/ __init__.py models.py templatetags/ # templatetags包 __init__.py app01_myfilter.py # 創建存放自定義filter(過濾器)的文件 admin.py apps.py views.py
然后,是編寫自定義filter過濾器:
app01_myfilters.py文件代碼如下:步驟是 1 >> 2 >> 3
# 1. 首先需要引入template模塊,並創建一個library注冊對象 from django import template register = template.Library() # 2. 接着才是正式編輯filter @register.filter(name="addsb") # 3. 注冊filter(filter的別名為addsb):寫好下面的自定義filter函數后,需要注冊過濾器,用裝飾器函數形式即可 def add_sb(value): # 定義不帶參數的自定義filter函數 return "{} SB.".format(value) @register.filter(name="add_str") # 3. 注冊filter(filter的別名為add_str):同上 def add_str(value, arg): # 定義帶一個參數的自定義filter return "{} {}.".format(value, arg) # 注意:第一個參數(value)永遠是管道符前面那個變量,第二個以后才是參數
最后,是使用自定義filter過濾器
1. 需要在template模塊下面的模板中,引入自定義過濾器的文件模塊如下:
{% load app01_myfilters %}
2. 結合變量使用自定義的filter過濾器
<p>不帶參數自定義filter:{{ myname|addsb }}</p>
<p>帶參數的自定義filter:{{ myname|addstr:"牛逼" }}</p>
解析:管道符 ” | “ 的左邊的myname是views.py模塊提供的變量,右邊的addsb是自定義的filter過濾器,而冒號 ” : “的右邊則是自己寫的參數。
如果myname的值為 myname = "my name is"
帶入上面的的自定義filter過濾器后結果如下:
不帶參數自定義filter:my name is sb.
帶參數的自定義filter:my name is 牛逼.
創建自定義的filter過濾器簡單步驟:
第一. 首先創建templatetags python包,接着重新啟動項目,最后創建用於存放自定義filter過濾器的.py文件
第二. 首先引入django下面的template模塊,接着編寫自定義的filter過濾器函數,最后使用裝飾器的形式注冊過濾器函數,並通過name定義過濾器的名稱(過濾器函數的別名)
第三. 首先,在模板語言中,使用{% load 自定義filter名稱%}引入自定義filter過濾器,接着在引入的下面開始使用過濾器即可。
3.14
3.15
3.16
4. Tags(邏輯標簽)
4.1 for循環
普通for循環
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
for循環可用的一些參數:
Variable | Description |
---|---|
forloop.counter |
當前循環的索引值(從1開始) |
forloop.counter0 |
當前循環的索引值(從0開始) |
forloop.revcounter |
當前循環的倒序索引值(從1開始) |
forloop.revcounter0 |
當前循環的倒序索引值(從0開始) |
forloop.first |
當前循環是不是第一次循環(布爾值) |
forloop.last |
當前循環是不是最后一次循環(布爾值) |
forloop.parentloop |
本層循環的外層循環 |
for ... empty for循環
當下面的user_list里面的內容為空,或者user_list根本不存在的時候,for循環會自動跳轉到empty程序塊,並且執行(如果是下面的話就是得到:空空如也)。
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% empty %}
<li>空空如也</li>
{% endfor %}
</ul>
4.2 if判斷
if……else 語句
{% if user_list|length > 5 %} 用戶數超過5人 {% else %}
用戶數小於等於5人,或沒有用戶
{% endif %}
if……elif……
else語句
{% if user_list %} 用戶人數:{{ user_list|length }} {% elif black_list %} 黑名單數:{{ black_list|length }} {% else %} 沒有用戶 {% endif %}
if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷。
4.3 with語句
當一個變量很長很復雜的時候,定義一個中間變量,多用於給一個復雜的變量起別名。
例如一個名字的列表name_list2 = [['張三0', '李四0', '王五0'], ['張三1', ['張三1.1', '李四1.1', '王五1.1'], '王五1']]
當我們要取 " 李四1.1 " 的時候,就是 " name_list2.1.1.1 "這個時候就覺得 name_list2.1.1.1比較長,
而在某個模板語言的某個程序塊中會一直用到這個,所以我們需要給它起一個別名,主要目的是為了方便操作
起別名的方法有一下兩種方式:
注意:等號左右不要加空格。
{% with total=name_list2.1.1.1%}
{{ total }} with語法{{ total|pluralize }}
{% endwith %}
或
{% with name_list2.1.1.1 as total %}
{{ total }} with語法{{ total|pluralize }}
{% endwith %}
4.4 csrf_token
這個標簽用於跨站請求偽造保護。
在頁面的form表單里面寫上{% csrf_token %}
4.5 注釋
{# 注釋內容... #}
4.6 模板語言使用注意事項
1. Django的模板語言不支持連續判斷,即不支持以下寫法:
{% if a > b > c %} ... {% endif %}
2. Django的模板語言中屬性的優先級大於方法
def xx(request): d = {"a": 1, "b": 2, "c": 3, "items": "100"} return render(request, "xx.html", {"data": d})
如上,我們在使用render方法渲染一個頁面的時候,傳的字典d有一個key是items並且還有默認的 d.items() 方法,此時在模板語言中:
{{ data.items }}
默認會取d的items key的值。
5. 母版(模板)
注意:我們通常會在母板中定義頁面專用的CSS塊和JS塊,方便子頁面替換。
5.1繼承母版
在子頁面中的第一行代碼必須使用下面的語法來繼承母版,其中base.html是母版文件!
{% extends 'base.html' %}
5.2母版與繼承母版的注意事項:
1.子頁面中的繼承母版的語句一定要放在第一行!
2.{% extends 'base.html' %},繼承語法中的母版名稱位置,是有引號的
3.在母版文件base,html中,是會定義很多塊(block)的,但是我們會固定的另外定義page-js和pafe-css兩個塊
4.在view.py中的對應關系的函數,返回的是子頁面的!!而不是母版哦!!!
5.3塊(block)
在母版中使用塊的語法定義:{% block page-main %} …………{% endblock % }。塊的名字:page-main
例如:這條語句已經在木板文件中定義了。那接下這子頁面中的應用如下:
//子頁面中對應母版的塊的定義 {% block page-main %} //首尾語法與母版中一模一樣 <div class="content">
<p> 我想寫一首詩<br/></p> <p> 記錄我對你的思念</p> <p> 我想寫一首詩</p> <p> 記下這痛苦的瞬間</p> <p> 我想寫一首詩</p> <p> 記住這慘痛的教訓</p> <p> 我想唱一曲歌</p> <p> 唱出我思念你時的情懷</p> <p> 我想唱一首歌</p> <p> 唱到我幻想的浪漫深處</p> <p> 我想唱一支歌</p> <p> 歌頌我對你的痴情</p> <p> 可惜怯懦的我哽咽着哭泣,始終沒拿起也沒放棄</p> <p> 春光撫摸着我的愛意</p> <p> 夏日打擊着我的沖動</p> <p> 秋風嘲諷着我的深情</p> <p> 冬雪將我的軀干冰封</p> <p> 我無力掙扎,掙扎,掙扎</p> <p> 直到春暖融盡這刺骨的冰霜</p> <p> 夏炎炙烤着我的肢體</p> <p> 秋愁撕裂着我的心府</p> <p> 冬魔蠶食着我的生命</p> <p> 幾番風雨,幾多痴迷,幾度春秋……</p> <p> 啊!彩虹,那么近,那么亮</p> <p> 別告訴我那是地獄之火,我要去天堂;</p> <p> 別對我說那是天堂之光</p> <p> 錯了,我將留在這慘痛的人間!</p> <p> 去地獄的是佛,上天堂的是仙,我是人,卻不願留在虛偽的凡間</p> <p> 我一直走,走,走</p> <p> 沒有盡頭,決不回頭,只期盼有一天能碰頭……</p> </div> {% endblock %} //首尾語法與母版中一模一樣
5.4 為什么要有模板和繼承?
把多個頁面公用的部分提取出來,放在一個 母版 里面。
其他的頁面只需要 繼承 母版就可以了。
5.5 使用模板的基本步驟:
1.把所有THML網頁的公用(相同部分)提取出來,一同放到母版文件中,(一般來說母版文件的命名都是base.html)
2.在base.html中,通過塊的語法定義未來子頁面中會存在的塊,注意塊名一定要有意義
3.在子頁面的第一行一定要先繼承母版:{% extends 'base.html' %}
4.子頁面的編輯:子頁面中想要展示的內容要放到塊的語法當中,例如:{% block page-main %} ……html代碼……{% endblock %},注意block(塊)名要正確指定母版中的相應位置才行!!
6. 組件
為了更好的體現代碼的復用性,我們可以將所有html頁面中常用的功能代碼塊提取出來,例如:導航條、頁尾信息等固定的重復的代碼單獨的保存到單獨的文件中,形成一個獨立的功能模塊,這就是組件。當我們在創建新的頁面的時候,正好需要使用這些功能的時,就可以隨時通過特定語法導入組件的文件就可以就可以了!!!
其實組件就是一個帶有特定的固定的功能的html文件而已,‘組件’只是一個名詞一個稱呼而已!
導入組件的語法:
{% include 'nav.html' %} // 假設 nav.html 是導航的代碼,那通過這個導入語法,就可以把導航里面的代碼引入到頁面當中了
7. 靜態文件相關
7.1 {% static %}
引用CSS文件時使用:
{% load static %}
<img src="{% static "mystyle.css" %}" />
引用JS文件時使用:
{% load static %}
<script src="{% static "mytest.js" %}"></script>
某個文件多處被用到可以存為一個變量(起別名)
{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>
注意:static是Django內置的一個模塊方法,因為,static可以從配置文件(setting.py)中的 STATIC_URL = '/static/' 和 STATICFILES_DIRS = []找到對應靜態文件所在路徑。
這樣做有什么好處呢?例如:一個模板中引入一個css文件的方法為:
<link rel="stylesheet" href="/static/fontawesome/css/font-awesome.min.css">
大家是不是以為上面這條引入css語句中的 “ static ” 直接是,項目文件中static文件呢?其實不是的!!!!!!
其實這個static是 STATIC_URL = '/static/' 中的static,而真實的路徑是由 STATICFILES_DIRS = [] 里面的路徑自動拼接而得到的!
7.2 {% get_static_prefix %}
{% load static %} <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />
或者
{% load static %} {% get_static_prefix as STATIC_PREFIX %} <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" /> <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />
get_static_prefix:是一個可以獲取到 ' /static/ '字符串的函數,通過獲取到的' /static/ '字符串手動拼接一條路徑!
8. tag
8.1 simple_tag
和自定義filter類似,只不過接收參數的形式更加靈活
1.首先,跟自定義的filter一樣,需要在“app01項目文件夾”創建一個存放simple_tag的py文件,可以命名為app01_mytag.py
2.第二,app01_mytag.py編輯,跟自定義的filter一樣,需要引入template,如下:
from django import template register = template.Library()
3.第三,app01_mytag.py編輯,注冊register中simple_tag裝飾器,如下:
@register.simple_tag(name="myjoin") def myjoin(arg1, arg2, arg3): return "{} + {} + {}".format(arg1, arg2, arg3)
4.第四,模板文件使用自定義的simple_tag
{% load app01_mytag %} #先加載,存放自定義simple_tag的py文件模塊 {% myjoin "aa" "bb" "cc" %} #正式使用裝飾器,語法格式:{% 函數名或者注冊的時候起的別名 參數1 參數2 參數3…… %}
5.結果,result >> aabbcc
8.2 inclusion_tag
更多的時候用於返回html代碼片段,
注冊的時候跟自定義filter和simple_tag的一樣。
1.首先,需要在“app01項目文件夾”創建一個存放inclusion_tag的py文件,可以命名為app01_mytag_inclu.py。或者自定義的inclusion_tag函數和simple_tag一起放在同一文件
2.第二,app01_mytag_inclu.py編輯,同樣需要引入template,如下:
from django import template register = template.Library()
3.第三,app01_mytag_inclu.py編輯,同樣是需要注冊,但這里注冊是的inclusion_tag,如下:
@register.inclusion_tag( 'result.html' ) def foo_result(n): n = 1 if n < 1 else int(n) data = ["第{}項".format(i) for i in range(1, n+1)] return {"data": data}
4.第四,需要將第三步的結果引入到result.html,進行字符串的替換之后,得到的html代碼片段,才會返回給使用inclusion_tag的模板
result.html代碼:
<ul> {% for choice in data %} <li>{{ choice }}</li> {% endfor %} </ul>
5.第五,模板文件使用自定義的inclusion_tag
{% load app01_mytag_inclu %} # 加載inclusion_tag所在的文件模塊
{% foo_result 10 %} # 使用裝飾器,語法格式:{% 函數名 參數1 參數2 …… %}