Django - 模板層 - 變數、過濾器、標籤
目錄
三、模板語法 - 過濾器 :{{ 位置引數1 | 過濾器函式 : 位置引數2}}
1- default :如果一個變數是false或者為空,使用給定的預設值。否則,使用變數的值。
2- length : 返回值的長度。它對字串和列表都起作用
3- filesizeformat :將值格式化為一個可讀性高的檔案尺寸
6- truncatechars :如果字串字元多於指定的字元數量,那麼會被截斷。截斷的字串將以可翻譯的省略號序列(“...”)結尾。
7- safe :是否轉義輸入框內的html、js元素等(使用-轉義;不使用-不轉義)
四、模板語法 - 標籤 : {% tag %} …… {% endtag%}
1-2 for …… empty :若迴圈物件為空執行empty內程式碼塊
4、csrf_token 標籤:跨站請求偽造保護 {% csrf_token%}
1、自定義標籤(引數不限,但不能放在if for語句中)- @register.simple_tag
1-1 @register.inclusion_tag --- 返回可迭代物件(qureyset物件)
一、模板概念
你可能已經注意到我們在例子檢視中返回文字的方式有點特別。 也就是說,HTML被直接硬編碼在 Python程式碼之中。
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
儘管這種技術便於解釋檢視是如何工作的,但直接將HTML硬編碼到你的視圖裡卻並不是一個好主意。
對頁面設計進行的任何改變都必須對 Python 程式碼進行相應的修改。 站點設計的修改往往比底層 Python 程式碼的修改要頻繁得多,因此如果可以在不進行 Python 程式碼修改的情況下變更設計,那將會方便得多。
Python 程式碼編寫和 HTML 設計是兩項不同的工作,大多數專業的網站開發環境都將他們分配給不同的人員(甚至不同部門)來完成。 設計者和HTML/CSS的編碼人員不應該被要求去編輯Python的程式碼來完成他們的工作。
程式設計師編寫 Python程式碼和設計人員製作模板兩項工作同時進行的效率是最高的,遠勝於讓一個人等待另一個人完成對某個既包含 Python又包含 HTML 的檔案的編輯工作。
因此,將頁面的設計和Python的程式碼分離開會更乾淨簡潔更容易維護。 我們可以使用 Django的 模板系統 (Template System)來實現這種模式,這就是本章要具體討論的問題
python的模板:HTML程式碼+模板語法
# 檢視函式 傳輸資料給模板 def inde_action(request): # 推薦寫法 name = 'name1' list00 = [1,2,3,'hello','django'] dic = {'name':'name2','age':18} def test(): print('hello world') return 'fun-test' class Person(): pass # locals()方法可以返回檢視函式內所有定義的 變數、函式、類等 return render(request, 'index.html', locals())
二、 模板語法 - 變數 : {{ 變數 }}
1、直接呼叫輸出 - 相當於print
{#模板語言註釋:前端看不到#} {#相當於print了該變數#} <h1>模板語言之變數</h1> <p>字串:{{ name }}</p> <p>數字:{{ age }}</p> <p>列表:{{ ll }}</p> <p>元組:{{ tu }}</p> <p>字典:{{ dic }}</p> {#只寫函式名:相當於函式名(),執行該函式,顯示的是返回值#} <p>函式:{{ test }}</p> {#物件呼叫顯示記憶體地址#} <p>物件:{{ lqz }}</p> {# person_list=[p1,p2] #} <p>列表套物件:{{ person_list }}</p> {# person_dic={'p1':p1} #} <p>字典套物件:{{ person_dic }}</p>
2、深度取值 - 獲取物件內部值
<h1>深度查詢</h1> {# 一層 #} <p>列表第0個值:{{ ll.0 }}</p> <p>列表第4個值:{{ ll.3 }}</p> <p>字典取值:{{ dic.name }}</p> <p>字典取列表值:{{ dic.ll }}</p> {# 二層 #} <p>物件取資料屬性:{{ p1.name }}</p> <p>物件取繫結給物件的函式屬性:{{ p1.get_name }}</p> <p>物件取繫結給類的函式屬性:{{ p1.cls_test }}</p> <p>物件取靜態方法:{{ p1.static_test }}</p> <p>把物件列表中,其中物件的一個年齡屬性取出來:{{ person_list.1.age }}</p> {# 注意:不能調有引數的方法 #} <p>字串的方法:{{ name.upper }}</p>
三、模板語法 - 過濾器 :{{ 位置引數1 | 過濾器函式 : 位置引數2}}
1- default :如果一個變數是false或者為空,使用給定的預設值。否則,使用變數的值。
{{ value|default:"nothing" }}
2- length : 返回值的長度。它對字串和列表都起作用
{{ value|length }} {#如果 value 是 ['a', 'b', 'c', 'd'],那麼輸出是 4。#}
3-
filesizeformat :
將值格式化為一個可讀性高的檔案尺寸{{ value|filesizeformat }} {# 如果 value 是 123456789,輸出將會是 117.7 MB #}
4- date :格式化日期
value=datetime.datetime.now() {{ value|date:"Y-m-d" }} {# 不使用date:Nov. 9, 2018, 6:51 p.m. #} {# date:2018-11-09 #}
5- slice:切片操作
{#前閉後開區間#} <p>過濾器之slice:{{ ll|slice:'2:-1' }}</p> {#支援步長#} <p>過濾器之slice-字串:{{ name|slice:'0:3:3' }}</p>
6- truncatechars :如果字串字元多於指定的字元數量,那麼會被截斷。截斷的字串將以可翻譯的省略號序列(“...”)結尾。
{# 字串 | truncatechars:顯示的詞數(三個起步)#} <p>過濾器之truncatechars:{{ 'dafddfafgadfgaasdgadgfadaf'|truncatechars:5 }}</p> {# da... #} <p>過濾器之truncatewords:{{ '我 dfaf ga dfgaas 你 dgf adaf'|truncatewords:5 }}</p> {# 我 dfaf ga dfgaas 你 ... #}
7- safe :是否轉義輸入框內的html、js元素等(使用-轉義;不使用-不轉義)
Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,原因顯而易見,這樣是為了安全。
但是有的時候我們可能不希望這些HTML元素被轉義,比如我們做一個內容管理系統,後臺新增的文章中是經過修飾的,這些修飾可能是通過一個類似於FCKeditor編輯加註了HTML修飾符的文字,如果自動轉義的話顯示的就是保護HTML標籤的原始檔。
為了在Django中關閉HTML的自動轉義,通過過濾器“|safe”的方式告訴Django這段程式碼是安全。
{# h1='<h1>你好</h1>' #} <p>過濾器之不用safe:{{ h1 }}</p> <p>過濾器之用safe:{{ h1|safe }}</p> {# script='<script>alert(111)</script>' #} <p>過濾器之不用safe:{{ script }}</p> <p>過濾器之用safe:{{ script|safe }}</p>
8- 其他過濾器
過濾器 描述 示例 upper 以大寫方式輸出 {{ user.name | upper }} add 給value加上一個數值 {{ user.age | add:”5” }} addslashes 單引號加上轉義號 capfirst 第一個字母大寫 {{ ‘good’| capfirst }} 返回”Good” center 輸出指定長度的字串,把變數居中 {{ “abcd”| center:”50” }} cut 刪除指定字串 {{ “You are not a Englishman” | cut:”not” }} date 格式化日期 default 如果值不存在,則使用預設值代替 {{ value | default:”(N/A)” }} default_if_none 如果值為None, 則使用預設值代替 dictsort 按某欄位排序,變數必須是一個dictionary {% for moment in moments | dictsort:”id” %} dictsortreversed 按某欄位倒序排序,變數必須是dictionary divisibleby 判斷是否可以被數字整除 {{ 224 | divisibleby:2 }} 返回 True
escape 按HTML轉義,比如將”<”轉換為”<” filesizeformat 增加數字的可讀性,轉換結果為13KB,89MB,3Bytes等 {{ 1024 | filesizeformat }} 返回 1.0KB
first 返回列表的第1個元素,變數必須是一個列表 floatformat 轉換為指定精度的小數,預設保留1位小數 {{ 3.1415926 | floatformat:3 }} 返回 3.142 四捨五入 get_digit 從個位數開始擷取指定位置的數字 {{ 123456 | get_digit:’1’}} join 用指定分隔符連線列表 {{ [‘abc’,’45’] | join:’’ }} 返回 abc45 length 返回列表中元素的個數或字串長度 length_is 檢查列表,字串長度是否符合指定的值 {{ ‘hello’| length_is:’3’ }} linebreaks 用<p>或<br>標籤包裹變數 {{ “Hi\n\nDavid”|linebreaks }} 返回<p>Hi</p><p>David</p> linebreaksbr 用<br/>標籤代替換行符 linenumbers 為變數中的每一行加上行號 ljust 輸出指定長度的字串,變數左對齊 {{‘ab’|ljust:5}}返回 ‘ab ’ lower 字串變小寫 make_list 將字串轉換為列表 pluralize 根據數字確定是否輸出英文複數符號 random 返回列表的隨機一項 removetags 刪除字串中指定的HTML標記 {{value | removetags: “h1 h2”}} rjust 輸出指定長度的字串,變數右對齊 slice 切片操作, 返回列表 {{[3,9,1] | slice:’:2’}} 返回 [3,9] {{ 'asdikfjhihgie' | slice:':5' }} 返回 ‘asdik’
slugify 在字串中留下減號和下劃線,其它符號刪除,空格用減號替換 {{ '5-2=3and5 2=3' | slugify }} 返回 5-23and5-23
stringformat 字串格式化,語法同python time 返回日期的時間部分 timesince 以“到現在為止過了多長時間”顯示時間變數 結果可能為 45days, 3 hours timeuntil 以“從現在開始到時間變數”還有多長時間顯示時間變數 title 每個單詞首字母大寫 truncatewords 將字串轉換為省略表達方式 {{ 'This is a pen' | truncatewords:2 }}返回``This is ...
truncatewords_html 同上,但保留其中的HTML標籤 {{ '<p>This is a pen</p>' | truncatewords:2 }}返回``<p>This is ...</p>
urlencode 將字串中的特殊字元轉換為url兼容表達方式 {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}} urlize 將變數字串中的url由純文字變為連結 wordcount 返回變數字串中的單詞數 yesno 將布林變數轉換為字串yes, no 或maybe {{ True | yesno }}{{ False | yesno }}{{ None | yesno }} ``返回 ``yes``no ``maybe
四、模板語法 - 標籤 : {% tag %} …… {% endtag%}
標籤比變數更加複雜:一些在輸出中建立文字,一些通過迴圈或邏輯來控制流程,一些載入其後的變數將使用到的額外資訊到模版中。一些標籤需要開始和結束標籤 (例如
{% tag %} ...
標籤 內容 ... {% endtag %})。1- for標籤:迴圈結構
列表的迴圈: {% for person in person_list %} <p>{{ person.name }}</p> {% endfor %} 字典的迴圈: {% for key in dic %} <p>{{ key }}</p> {% endfor %} {% for val in dic.values %} <p>{{ val }}</p> {% endfor %} {% for key,val in dic.items %} <p>{{ key }}:{{ val }}</p> {% endfor %} 模板: {% for i in list %} {{ i }} {% endfor %}
1-1 檢視迴圈資訊:{{ forloop }}
{% for foo in ll %} {{ forloop }} <p>{{ forloop.first }}--->{{ forloop.counter0 }}--->{{ forloop.revcounter }}----->{{ foo }}</p> {% endfor %} {% for foo in ll %} {% for i in person_list %} 取出外層是第幾次迴圈 {{ forloop.parentloop.counter }} <p>{{ forloop.first }}--->{{ forloop.counter0 }}--->{{ forloop.revcounter }}----->{{ foo }}</p> {% endfor %} {% endfor %}
{{ forloop }}的輸出資訊: {'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
forloop.counter 當前迴圈的索引值(從1開始) forloop.counter0 當前迴圈的索引值(從0開始) forloop.revcounter 當前迴圈的倒序索引值(從1開始) forloop.revcounter0 當前迴圈的倒序索引值(從0開始) forloop.first 當前迴圈是不是第一次迴圈(布林值) forloop.last 當前迴圈是不是最後一次迴圈(布林值) forloop.parentloop 本層迴圈的外層迴圈 1-2 for …… empty :若迴圈物件為空執行empty內程式碼塊
{% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
2、if標籤:邏輯判斷
{% if %}會對一個變數求值,如果它的值是“True”(存在、不為空、且不是boolean型別的false值),對應的內容塊會輸出。 {% if num > 100 or num < 0 %} <p>無效</p> {% elif num > 80 and num < 100 %} <p>優秀</p> {% else %} <p>湊活吧</p> {% endif %} 模板(if語句支援 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷): {% if …… %} …… {% elif …… %} …… {% else %} …… {% endif %}
3、with 標籤: 取別名,簡化變數名
{% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %} 模板: {% with 別名=原名 %} {{ 別名 }} …… {% endwith %}
4、csrf_token 標籤:跨站請求偽造保護 {% csrf_token%}
五、自定義模板語法
1、自定義標籤(
引數不限,但不能放在
if
for
語句中
)- @register.simple_tag
- 確認app在setting內的INSTALLED_APPS註冊
- app下建立一個templatetags(固定名稱)的資料夾(模組)
- 建立任意 .py 檔案,如:my_tags.py
# 第一步,匯入template from django import template #或者 from django.template import Library from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改變 @register.simple_tag(name = 'xxx') 裝飾器內name可以對方法起別名 def simple_tag_multi(v1,v2): return v1 * v2 #一定要有返回值 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
- 在模板裡:(新定定義的標籤,過濾器,都要重啟程式)
{# 載入自己的標籤檔名 #} {% load mytag %} {# 使用標籤 #} {% add_nb 'name'%} {% add_3 'name1' 'name2'%} 多個引數以空格區分
1-1 @register.inclusion_tag --- 返回可迭代物件(qureyset物件)
注意:普通的自定義標籤返回的都只是一個值,而inclusion_tag返回一個可迭代物件
# 第一步,匯入template from django import template #或者 from django.template import Library register = template.Library() #register的名字是固定的,不可改變 # @register.inclusion_tag('模板路徑',name=‘重新命名’) @register.inclusion_tag('test.html',name = 'xxx') 裝飾器內name可以對方法起別名 def my_inclusion_1(): # 邏輯程式碼塊…… ret = Book.object.all() return {'books':ret} # 一定要有返回值,並且返回值必須是字典 @register.inclusion_tag('test.html') def my_inclusion_2(v1,v2): # 邏輯程式碼塊…… ret = Book.object.all().filter(v1=v1,v2=v2) return {'books':ret}
{# 模板中使用自定義inclusion_tag #} {# 載入自己的標籤檔名 #} {% load mytag %} {# 使用標籤 #} {% my_inclusion_1 %} {% my_inclusion_2 'v1' 'v2'%} 多個引數以空格區分
2、自定義過濾器 - @register.filter
- 確認app在setting內的INSTALLED_APPS註冊
- app下建立一個templatetags(固定名稱)的資料夾(模組)
- 建立任意 .py 檔案,如:my_filter.py
# 第一步,匯入template from django.template import Library # 第二步,定義一個叫register的變數=template.Library() register = Library() # 第三步 # 裝飾器內name可以對方法起別名 @register.filter(name='yyy') def str_add(str1, str2): # 業務邏輯…… return str1 + str2 # 一定要有返回值
- 在模板裡:(新定定義的標籤,過濾器,都要重啟程式)
匯入自己建立的過濾器檔案 {% load myfilter %} {{'name'|str_add:'hello'}}