Django模板渲染
{{ 變數 }}
{% 邏輯 %}
變數使用
看示例
Views.py檔案
def home(request): class A: def __init__(self): self.username = 'bob' #如果方法需要在模板中使用,那麼不能有其他引數 def xx(self): return 'bobxx' info= { 'name': 'jack', 'hobby': ['running', 'walking', 'reading'], 'num': 100, 'd1':{'aa':'bb'}, 'l1':[11,22,{'cc':'dd'}], 'a': A(), } return render(request, 'home.html', info)
重點:萬能的據點號。通過點可以進行資料的索引取值,屬性取值,取方法等等
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>{{ name }}</h2> <ul> {% for i in hobby %} <li>{{ i }}</li> {% endfor %} </ul> <hr> {{ num }} <p> {{ l1.2.ss }}</p> <p> {{ d1.xx }} </p> <p> {{ a.username }} </p> <p> {{ a.xx }} <!-- 方法不能加括號,意味著不能穿引數,也就是說你後面定義的方法,不能有引數 --> </p> </body> </html>
urls.py內容
url(r'^home/', views.home),
在Django的模板語言中,通過使用 過濾器 來改變變數的顯示。
過濾器的語法:{{ value|filter_name:引數 }}
使用過濾器的注意事項
1. 過濾器支援“鏈式”操作。即一個過濾器的輸出作為另一個過濾器的輸入。
2. {{ sss|過濾器1:30|過濾器2.... }}
3. 過濾器可以接受引數,例如:{{ sss|truncatewords:30 }},這將顯示sss的前30個詞。
4. '|'左右沒有空格
內建過濾器
常用的內建過濾器示例
(1) default
如果一個變數是false或者為空,使用給定的預設值。 否則,使用變數的值。
{{ value|default:"nothing"}}
如果value沒有傳值或者值為空或者為False的話就顯示nothing
(2) length
{{ value|length }}
返回value的長度,如 value=['a', 'b', 'c', 'd']的話,就顯示4.
(3) filesizeformat
將值格式化為一個 “人類可讀的” 檔案尺寸 (例如 '13 KB'
, '4.1 MB'
, '102 bytes'
, 等等)。例如:
{{ value|filesizeformat }}
如果 value 是 123456789,輸出將會是 117.7 MB。
(4) slice
切片,如果 value="hello world",還有其他可切片的資料型別
{{value|slice:"2:-1"}}
(5) date
格式化,如果 value=datetime.datetime.now(),如果不想顯示為UTC時間,將django的settings.py配置檔案中的TIME_ZONE這一項修改一下,修改為TIME_ZONE = 'Asia/Shanghai'
比如,後臺返回的資料為{'value':datetime.datetime.now()}
對上面的資料進行格式化:{{ value|date:"Y-m-d H:i:s"}}
關於時間日期的可用的引數(除了Y,m,d等等)還有很多,有興趣的可以去查檢視看。
(6) safe
xxs攻擊,全稱跨站指令碼攻擊 Django的模板中在進行模板渲染的時候會對HTML標籤和JS等語法標籤進行自動轉義,原因顯而易見,這樣是為了安全,django擔心這是使用者新增的資料,比如如果有人給你評論的時候寫了一段js程式碼,這個評論一提交,js程式碼就執行啦,這樣你是不是可以搞一些壞事兒了,寫個彈窗的死迴圈,那瀏覽器還能用嗎,是不是會一直彈窗啊,這叫做xss攻擊,所以瀏覽器不讓你這麼搞,給你轉義了。但是有的時候我們可能不希望這些HTML元素被轉義,比如我們做一個內容管理系統,後臺新增的文章中是經過修飾的,這些修飾可能是通過一個類似於FCKeditor編輯加註了HTML修飾符的文字,如果自動轉義的話顯示的就是保護HTML標籤的原始檔。為了在Django中關閉HTML的自動轉義有兩種方式,如果是一個單獨的變數我們可以通過過濾器“|safe”的方式告訴Django這段程式碼是安全的不必轉義。
{'a_tag':'<a href="">百度</a>',} 渲染 <p> {{ a_tag|safe }} #生成標籤效果 </p>
(7) truncatechars
如果字串字元多於指定的字元數量,那麼會被截斷。截斷的字串將以可翻譯的省略號序列(“...”)結尾。
引數:截斷的字元數
{{ value|truncatechars:9}} #注意:最後那三個省略號也是9個字元裡面的,也就是這個9截斷出來的是6個字元+3個省略號,有人會說,怎麼展開啊,配合前端的點選事件就行啦
(8) truncatewords
在一定數量的字後截斷字串,是截多少個單詞。
例如:‘are you ok’,
{{ value|truncatewords:2}} #上面例子得到的結果是 'are you...'
(9) cut
移除value中所有的與給出的變數相同的字串
{{ value|cut:' ' }}
如果value為'i love you',那麼將輸出'iloveyou'.
(10) join
使用字串連線列表,{{ list|join:', ' }},就像Python的str.join(list)
<p>{{ hobby|join:'+' }}</p>
注意:模版渲染在瀏覽器渲染之前,模板渲染就是字串替換,替換完成之後,將替換完的整體檔案字串返回給瀏覽器,瀏覽器再進行瀏覽器渲染,展示頁面效果
標籤
語法{% 標籤 %}
(1) for迴圈標籤
示例:
#迴圈列表 <ul> {% for xx in hobby %} <li>{{ xx }}</li> {% empty %} #當hobby為空或者後臺沒有給這個資料,那麼會顯示empty下面的內容 <h2>抱歉,沒有查詢到相關資料</h2> {% endfor %} </ul> #迴圈字典 <ul> {% for k,v in d1.items %} <!-- 直接迴圈字典資料,那麼是迴圈字典的key,迴圈d1.values,那麼表示迴圈字典的值, 迴圈d1.items,那麼k,v表示鍵和值--> <li>{{ k }}--{{ v }}</li> {% endfor %} </ul> #迴圈計數 <ul> {% for i in l1 %} {# {{ forloop }}#} {% for h in hobby %} <li>{{ forloop.parentloop.counter }}--{{ forloop.revcounter0 }}---{{ h }}--{{ forloop.last }}</li> {% endfor %} {% endfor %} </ul> forloop的解釋 注:迴圈序號可以通過{{forloop}}顯示,必須在迴圈內部用 forloop.counter 當前迴圈的索引值(從1開始),forloop是迴圈器,通過點來使用功能 forloop.counter0 當前迴圈的索引值(從0開始) forloop.revcounter 當前迴圈的倒序索引值(從1開始) forloop.revcounter0 當前迴圈的倒序索引值(從0開始) forloop.first 當前迴圈是不是第一次迴圈(布林值) forloop.last 當前迴圈是不是最後一次迴圈(布林值) forloop.parentloop 本層迴圈的外層迴圈的物件,再通過上面的幾個屬性來顯示外層迴圈的計數等 #反向迴圈 可以利用{% for obj in list reversed %}反向完成迴圈。 示例: <ul> {% for xx in hobby reversed %} <li>{{ xx }}</li> {% endfor %} </ul>
(2) if 標籤
{% if %}
會對一個變數求值,如果它的值是“True”(存在、不為空、且不是boolean型別的false值),對應的內容塊會輸出。
{% if num > 100 or num < 0 %} <p>無效</p> <!--不滿足條件,不會生成這個標籤--> {% elif num > 80 and num < 100 %} <p>優秀</p> {% else %} <!--也是在if標籤結構裡面的--> <p>湊活吧</p> {% endif %}
當然也可以只有if和else
{% if user_list|length > 5 %} <!--結合過濾器來使用--> 七座豪華SUV {% else %} 黃包車 {% endif %}
if語句支援 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷,注意條件兩邊都有空格。
(3) with標籤
使用一個簡單地名字快取一個複雜的變數,多用於給一個複雜的變數起別名,當你需要使用一個“昂貴的”方法(比如訪問資料庫)很多次的時候是非常有用的
例如:
注意等號左右不要加空格。
{% with total=business.employees.count %} {{ total }} <!--只能在with語句體內用--> {% endwith %}
或
{% with business.employees.count as total %}
{{ total }}
{% endwith %}
使用標籤的注意事項
1. Django的模板語言不支援連續判斷,即不支援以下寫法:
{% if a > b > c %}
...
{% endif %}
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的值。
自定義標籤和過濾器
自定義過濾器
注意:在settings中的INSTALLED_APPS配置當前app,不然django無法找到自定義的simple_tag.
1、在app中建立templatetags資料夾(資料夾名只能是templatetags)
2、在templatetags資料夾中建立任意 .py 檔案,如:mytag.py
3、在mytag.py檔案中寫上如下內容
from django import template register = template.Library() #製作註冊器,名字必須叫register #過濾最多兩個引數 @register.filter #註冊過濾器,需要兩個引數的 def add(v1, v2): #v1表示管道符前面的,v2表示冒號後面的引數 print(v1,v2) #100 50 return v1 + v2 @register.filter #註冊過濾器,需要一個引數的 def xxx(v1): #v1表示管道符前面的 print(v1) return 'xxx'
4、使用,在html檔案中寫上如下內容
{% load mytag %} <!-- 首先通過load來載入一下mytag檔案,不一定放在檔案的開頭,但是一定要放在使用過濾器的前面先進行引用 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>base頁面</h1> <!--{% load mytag %} 放這裡也是可以的--> <div> {{ num|add:50}} <!-- 使用過濾器,和django內建過濾器用法一樣,這裡生成的是add函式的返回值 --> </div> <div> {{ num|xxx }} </div> <!--{% load mytag %} 放這裡不行--> </body> </html>
自定義標籤
過程:
1、在app中建立templatetags資料夾(資料夾名只能是templatetags)
2、在templatetags資料夾中建立任意 .py 檔案,如:mytag.py
3、在mytag.py檔案中寫上如下內容
from django import template register = template.Library() #製作註冊器,名字必須叫register @register.simple_tag def atag(v1,v2): #沒有引數個數限制 print(v1,v2) return v1 + v2
4、使用,在html檔案中寫上如下內容
{#{% load mytag %}#} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>base頁面</h1> {% load mytag %} <div> {% atag 'a' 'b' %} <!-- 注意,是{%%} 來包裹使用,先是標籤名稱然後空格寫引數,引數之間也是空格分隔的 --> </div> </body> </html>
將一些頁面公共的部分,可以抽離出來單獨做成一個html頁面,使用這些公用部分的其他html檔案,只需要繼承一下它就可以了,具體使用流程如下:
1 建立公用模板,比如內容如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> body{ padding: 0; margin: 0; } {% block css %} .nav{ height: 60px; background-color: green; } {% endblock %} .nav a{ color:white; text-decoration: none; } .left-menu{ width: 30%; background-color: rgba(0,0,0,0.5); float:left; } .menu .menu-title{ text-align: center; } .main{ float: right; width: 65%; height: 300px; border: 1px solid red; } </style> </head> <body> <div class="nav"> <a href="/xx1/">首頁</a> <a href="/person/">個人中心</a> <a href="/detail/">詳情頁</a> </div> <div class="left-menu"> <div class="menu"> <div class="menu-title">選單1</div> <div class="menu-body"> <div class="item">包子</div> <div class="item">饅頭</div> <div class="item">涼皮</div> <div class="item">麵條</div> </div> <div class="menu-title">選單2</div> <div class="menu-body"> <div class="item">排骨藕湯</div> <div class="item">粉蒸肉</div> <div class="item">臘魚塊</div> <div class="item">灌腸</div> </div> </div> </div> <div class="main"> {% block content %} 公共頁面 {% endblock %} </div> </body> {% block js %} {% endblock %} </html>
2 將來如果說繼承公用模板的html檔案中需要修改公用模板中的一些內容,那麼需要在公用模板中預留一些鉤子,鉤子的寫法如下
{% block content %} #block 後面的塊名稱隨便起
公共頁面
{% endblock %}
#也可以這樣寫 {% endblock content %} #endblock指定名稱
3 繼承公用模板需要在html檔案中寫如下內容:
{% extends 'xx.html' %} <!-- 需要先繼承一下公用模板,寫法就是extends '公用模板檔名稱',注意,必須寫在第一行 --> {% block css %} .nav{ height: 60px; background-color: pink; } {% endblock %} {% block content %} <h1>首頁</h1> {% endblock %}
4 在使用公用模板的其他html檔案中,如果需要更改公用模板裡面的內容,只需要在html檔案中寫上相同的鉤子,鉤子裡面寫上自定義的內容,寫法如下
{% block css %} .nav{ height: 60px; background-color: pink; } {% endblock %} {% block content %} <h1>首頁</h1> {% endblock %}
注意事項:
-
如果你在模版中使用
{% extends %}
標籤,它必須是模版中的第一個標籤。其他的任何情況下,模版繼承都將無法工作,模板渲染的時候django都不知道你在幹啥。 -
在base模版中設定越多的
{% block %}
標籤越好。請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數blocks中填充合理的預設內容,然後,只定義你需要的那一個。多一點鉤子總比少一點好。 -
如果你發現你自己在大量的模版中複製內容,那可能意味著你應該把內容移動到父模版中的一個
{% block %}
中。 -
{{ block super }}的使用,在子模板中也展示出父模板原來鉤子中的內容
{% block content %} <h1>首頁</h1> {{ block.super }} {% endblock %}
{% block content %}
...
{% endblock content %}
在大型模版中,這個方法幫你清楚的看到哪一個 {% block %}
標籤被關閉了。
不能在一個模版中定義多個相同名字的 block
標籤。
#兩個block都叫content,這種寫法是不對的 {% block content %} <h1>首頁</h1> {{ block.super }} {% endblock %} {% block content %} <h1>首頁</h1> {{ block.super }} {% endblock %}