一.語法
關於模板渲染你只需要記兩種特殊符號(語法):
{{ }}和 {% %}
變量相關的用{{}},邏輯相關的用{%%}。
二.變量
- 在Django的模板語言中按此語法使用:{{ 變量名 }}。
- 當模版引擎遇到一個變量,它將計算這個變量,然後用結果替換掉它本身。 變量的命名包括任何字母數字以及下劃線 ("_")的組合。
變量名稱中不能有空格或標點符號。 - 深度查詢據點符(.)在模板語言中有特殊的含義。當模版系統遇到點("."),它將以這樣的順序查詢:
字典查詢(Dictionary lookup)
屬性或方法查詢(Attribute or method lookup)
數字索引查詢(Numeric index lookup)
示例:
views.py:
def index1(request):
num = 10
name = '張三'
name_list = ['李四','王五']
dic = {'name':'test','age':23,'hoby':'girl'}
class Person:
def __init__(self):
self.name = 'dog'
def dream(self):
return 'dreamer'
a = Person() #返回一個對象
return render(request,'index1.html',{'num':num,'name':name,'name_list':name_list,'dic':dic,'a':a})
# return render(request,'index.html',locals())
#locals()獲取函數內容所有的變量,然後通過render方法給了index.html文件進行模板渲染,如果你圖省事,你可以用它,但是很多多餘的變量也被傳進去了,效率低
index1.html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>模板</h1>
<p>{{ num }}</p>
<p>{{ name }}</p>
<p>{{ name_list }}</p>
<p>{{ name_list.0 }}</p>
<p>{{ dic }}</p>
<p>{{ dic.age }}</p>
<p>{{ a.name }}</p>
</body>
</html>
三.過濾器
在Django的模板語言中,通過使用 過濾器 來改變變量的顯示。
過濾器的語法: {{ value|filter_name:參數 }}
使用管道符"|"來應用過濾器。
例如:{{ name|lower }}會將name變量應用lower過濾器之後再顯示它的值。lower在這裏的作用是將文本全都變成小寫。
注意事項:
- 過濾器支持“鏈式”操作。即一個過濾器的輸出作爲另一個過濾器的輸入。
- 過濾器可以接受參數,例如:{{ sss|truncatewords:30 }},這將顯示sss的前30個詞。
- 過濾器參數包含空格的話,必須用引號包裹起來。比如使用逗號和空格去連接一個列表中的元素,如:{{ list|join:’, ’ }}
- '|'左右沒有空格沒有空格沒有空格
Django的模板語言中提供了大約六十個內置過濾器。
length
返回值的長度,作用於字符串和列表。
{{ name_list|length }}
default
如果一個變量是false或者爲空,使用給定的默認值。 否則,使用變量的值。
{{ xx|default:'啥也沒有' }} #沒有xx這個值就顯示【啥也沒有】
filesizeformat
將值格式化爲一個 “人類可讀的” 文件尺寸 (例如 ‘13 KB’, ‘4.1 MB’, ‘102 bytes’, 等等)。例如:
movesizi = 123342224
{{ movesizi|filesizeformat }} #結果:117.6 MB
slice
切片,如果 value=“hello world”,還有其他可切片的數據類型
name = 'zhangsan'
{{ name|slice:'0:3' }} #zha
date
格式化,如果 value=datetime.datetime.now()
格式化,如果 value=datetime.datetime.now()
{{ now|date:'Y-m-d' }} #2020-03-12 不加date:March 12, 2020, 2:19 p.m.
truncatechars
如果字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(“…”)結尾。參數:截斷的字符數
words = 'i love you my girl'
{{ words|truncatechars:'9' }} #結果:i love... 點也算在內
truncatewords
在一定數量的字後截斷字符串,是截多少個單詞。
例如:‘hello girl hi baby yue ma’,
{{ words1|truncatewords:'3' }} #結果:hello girl hi ...
cut
移除value中所有的與給出的變量相同的字符串
words1 = 'hello girl hi baby yue ma'
{{ words1|cut:' ' }} #移除空格 結果:hellogirlhibabyyuema
join
使用字符串連接列表,{{ list|join:’, ’ }},就像Python的str.join(list)
name_list = ['李四','王五']
{{ name_list|join:'*' }} #以星號連接 結果:李四*王五
safe
Django的模板中在進行模板渲染的時候會對HTML標籤和JS等語法標籤進行自動轉義,原因顯而易見,這樣是爲了安全,django擔心這是用戶添加的數據,比如如果有人給你評論的時候寫了一段js代碼,這個評論一提交,js代碼就執行啦,這樣你是不是可以搞一些壞事兒了,這叫做xss攻擊,所以瀏覽器不讓你這麼搞,給你轉義了。但是有的時候我們可能不希望這些HTML元素被轉義,如果是一個單獨的變量我們可以通過過濾器“|safe”的方式告訴Django這段代碼是安全的不必轉義。
我們去network那個地方看看,瀏覽器看到的都是渲染之後的結果,通過network的response的那個部分可以看到,這個a標籤全部是特殊符號包裹起來的,並不是一個標籤,這都是django搞得事情。
使用safe之後,允許HTML元素被轉義,這個時候就是一個正常的a標籤了:
四.標籤Tags
標籤看起來像是這樣的: {% tag %}。標籤比變量更加複雜:一些在輸出中創建文本,一些通過循環或邏輯來控制流程,一些加載其後的變量將使用到的額外信息到模版中。一些標籤需要開始和結束標籤 (例如{% tag %} …標籤 內容 … {% endtag %})。
for標籤
遍歷每一個元素: 寫個for,然後 tab鍵自動生成for循環的結構,循環很基礎,就這麼簡單的用,沒有什麼break之類的,複雜一些的功能,你要通過js
列表:
<ul>
{% for name in name_list %}
<li>{{ name }}</li>
{% endfor %}
</ul>
字典:
<ol>
{% for key,value in dic.items %} #和Python裏面一樣 這裏可以循環key,values
<li>{{ key }}-----{{ value }}</li>
{% endfor %}
</ol>
循環序號:
注:循環序號可以通過{{forloop}}顯示,必須在循環內部用
forloop.counter 當前循環的索引值(從1開始),forloop是循環器,通過點來使用功能
forloop.counter0 當前循環的索引值(從0開始)
forloop.revcounter 當前循環的倒序索引值(從1開始)
forloop.revcounter0 當前循環的倒序索引值(從0開始)
forloop.first 當前循環是不是第一次循環(布爾值)
forloop.last 當前循環是不是最後一次循環(布爾值)
forloop.parentloop 本層循環的外層循環的對象,再通過上面的幾個屬性來顯示外層循環的計數等
forloop.parentloop示例:
d2 = [[11,22],[33,44]]
<ol>
{% for dd2 in d2 %}
<li>
{% for ddd2 in dd2 %}
{{ forloop.parentloop.counter }}
{{ forloop.counter}}
<a href="">{{ ddd2 }}</a>
{% endfor %}
</li>
{% endfor %}
</ol>
結果:
1 1 11 1 2 22
2 1 33 2 2 44
解釋:
父層循環裏面有兩個元素,第一次循環計數是1,內部循環裏面兩個值,第一次打印11 第二次打印22 計數分別爲1和2
父層循環裏面有兩個元素,第一次循環計數是2,內部循環裏面兩個值,第一次打印33 第二次打印44 計數分別爲1和2
for … empty
for 標籤帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,可以有所操作。
<ul>
{% for foo in d3 %}
<li>{{ foo }}</li>
{% empty %}
<li>什麼也沒有</li>
{% endfor %}
</ul>
if 標籤
{% if %}會對一個變量求值,如果它的值是“True”(存在、不爲空、且不是boolean類型的false值),對應的內容塊會輸出。
if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷,注意條件兩邊都有空格。
{% if num > 100 %}
<a href="">大於100</a>
{% elif num < 100 %}
<a href="">小於100</a>
{% endif %}
還可以加過濾器:
{% if name_list|length > 3%}
<a href="">大於3</a>
{% elif name_list|length < 3%}
<a href="">小於3</a>
{% else %}
<a href="">等於3</a>
{% endif %}
with
使用一個簡單地名字緩存一個複雜的變量,多用於給一個複雜的變量起別名,當你需要使用一個“昂貴的”方法(比如訪問數據庫)很多次的時候是非常有用的注意等號左右不要加空格。
<p>{{ dic.name }}</p>
第一種寫法:
{% with shitai=dic.name %}
<h2>{{ shitai }}</h2>
{% endwith %}
第二種寫法(as:類似與起別名):
{% with dic.name as shitai %}
<h2>{{ shitai }}</h2>
{% endwith %}
以上標籤注意事項:
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的值。並不是itemsl方法。
csrf_token
我們以post方式提交表單的時候,會報錯,還記得我們在settings裏面的中間件配置裏面把一個csrf的防禦機制給註銷了啊,本身不應該註銷的,而是應該學會怎麼使用它,並且不讓自己的操作被forbiden,通過這個東西就能搞定。
這個標籤用於跨站請求僞造保護,
五.模板繼承
Django模版引擎中最強大也是最複雜的部分就是模版繼承了。模版繼承可以讓您創建一個基本的“骨架”模版,它包含您站點中的全部元素,並且可以定義能夠被子模版覆蓋的 blocks 。
示例:
母版頁面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.nav{
background-color: red;
height: 40px;
}
.left_menu{
background-color: green;
color: white;
width: 20%;
height: 400px;
float: left;
}
.content{
width: 80%;
float: right;
}
.clearfix{
content: '';
display: block;
clear: both;
}
</style>
</head>
<body>
<div class="nav">
<a href="">22</a>
<a href="">23</a>
<a href="">24</a>
<input type="text"><button>搜索</button>
</div>
<div class="clearfix">
<div class="left_menu">
<ul>
<li><a href="{% url 'app02:menu1' %}">菜單1</a></li>
<li><a href="{% url 'app02:menu2' %}">菜單2</a></li>
<li><a href="{% url 'app02:menu3' %}">菜單3</a></li>
</ul>
</div>
<div class="content">
{% block content %}
母版頁面
{% endblock %}
</div>
</div>
</body>
</html>
{% extends 'object.html' %} #繼承母版頁面
{% block content %} #預留的鉤子 用來修改內容
{{ block.super }} #顯示父類的內容
首頁
{% endblock %}
{% extends 'object.html' %}
{% block content %}
菜單3
{% endblock %}
{% extends 'object.html' %}
{% block content %}
菜單2
{% endblock %}
{% extends 'object.html' %}
{% block content %}
菜單1
{% endblock %}
這裏是使用繼承的一些提示:
- 如果你在模版中使用 {% extends %}標籤,它必須是模版中的第一個標籤。其他的任何情況下,模版繼承都將無法工作,模板渲染的時候django都不知道你在幹啥。
- 在base模版中設置越多的 {% block %}標籤越好。請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數blocks中填充合理的默認內容,然後,只定義你需要的那一個。多一點鉤子總比少一點好。
- 如果你發現你自己在大量的模版中複製內容,那可能意味着你應該把內容移動到父模版中的一個 {% block %} 中。