一、模板介紹
Django的模板 = HTML程式碼 + 模板語法
存放在templates目錄下的HTML檔案就稱為模板檔案,如果我們想要返回 的HTML檔案中的資料是動態的,那麼就必須在HTML檔案中嵌入變數,這就會用到Django的模板語法。
二、變數
在Django的模板語言中的變數語法:
View:{ ' HTML變數名 ' : ‘ views變數名 ’ }
HTML:{{ 變數名 }}
views.py 檔案
from django.shortcuts import render
import time
def index(request):
times = time.time()
name = '小楊'
name_list = ['小楊', '艾倫', '鮑勃']
info_dict = {'name': '小楊', 'age': 18, 'job': '攻城獅'}
class A:
def __init__(self, hobby):
self.hobby = hobby
def func(self):
return self.hobby
# 也可以傳入物件
Bob = A('攻城獅')
# 將資料傳遞給 index.html 檔案進行渲染在傳送給瀏覽器
return render(request, 'index.html', {'times': times, 'Bob': Bob, 'name': name, 'name_list': name_list, 'info_dict': info_dict})
index.html檔案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 接收資料進行渲染 -->
<p>{{ times }}</p>
<p>{{ name }}</p>
<p>{{ name_list.2 }}</p> <!-- 取列表中索引為2的資料 -->
<p>{{ info_dict.age }}</p> <!-- 取字典中鍵值為age的資料 -->
<p>{{ Bob.func }}</p> <!-- 執行物件中的方法返回資料 -->
</body>
</html>
三、過濾器
過濾器類似於python的內建函式,用來把檢視傳入的變數加以修飾後在顯示
過濾器的語法:{{ 變數名|過濾器 : 可選引數 }}
注意事項:
- 過濾器支援“ 鏈式 ” 操作 。
- 過濾器引數包含空格需要用引號包裹起來。
- '|' 左右沒有空格
常用過濾器
default
如果一個變數是false或者是空,就使用給定的預設值。否則,使用變數的值。
{{ value|default:"預設值" }}
length
返回值的長度,主要用於字串和列表。
{{ value|length }}
filesizeformat
將值的格式轉換為一個可讀的,主要用於顯示檔案大小
如果 value 是 123456789,輸出將會是 117.7 MB。
{{ value|filesizeformat }}
slice
切片
{{ value|slice:"2:4" }}
date
格式化,若value = datetime.datetime.now()
{{ value|date:"Y-m-d H:i:s" }}
safe
轉義,若value是一串程式碼,就可以對其進行轉義成非程式碼的,防止xss攻擊。
{{ value|safe }}
truncatechars
如果字串的字元個數多於指定的字元數量,那麼就會被截斷。截斷的字串將以可翻譯的序號(...)結尾
{{ value|truncatechars:'6' }} # 後面的三個省略號也算在6個字元裡面
truncatewords
在一定數量的字後截斷字串,是截多少個單詞。
{{ value|truncatewords:2 }}
cut
移除value中所有的與給出的變數相同的字串
{{ value|cut:'移除的字元' }}
join
使用字串連線列表。
{{ list|join:', ' }}
四、標籤Tags
標籤是為了在模板中完成一些特殊功能,語法為{% 標籤名 %},一些標籤還需要搭配結束標籤 {% endtag %}
for 標籤
1、遍歷每一個元素
{% for food in foods_list %}
<p>{{ food }}</p>
{% endfor %}
2、可以利用{% for obj in list reversed %}反向迴圈。
{% for food in foods_list reversed %}
<p>{{ food }}</p>
{% endfor %}
3、遍歷一個字典
{% for k, v in f_dict.items %}
<p>{{ k }}:{{ v }}</p>
{% endfor %}
for ... empty
可選的{ % empty % } 從句,給出的組是空的或者沒有被找到時,執行的操作
{% for food in foods_list %}
<p>{{ food }}</p>
{% empty %}
<p>沒有foods_list,或者foods_list為空</p>
{% endfor %}
for迴圈的其他方法
forloop.counter 當前迴圈的索引值(從1開始),forloop是迴圈器,通過點來使用功能
forloop.counter0 當前迴圈的索引值(從0開始)
forloop.revcounter 當前迴圈的倒序索引值(從1開始)
forloop.revcounter0 當前迴圈的倒序索引值(從0開始)
forloop.first 當前迴圈是不是第一次迴圈(布林值)
forloop.last 當前迴圈是不是最後一次迴圈(布林值)
forloop.parentloop 本層迴圈的外層迴圈的物件,再通過上面的幾個屬性來顯示外層迴圈的計數等
forloop.parentloop.counter
if 標籤
對一個變數求值,如果它的值是“True” (存在,不為空,且不是boolean型別的False值),對應的內容塊會輸出。
if語句支援 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷,注意條件兩邊都有空格。
{% if num > 100 or num < 0 %}
<p>條件1滿足</p> <!--不滿足條件,不會生成這個標籤-->
{% elif num > 80 and num < 100 %}
<p>條件1不滿足,條件2滿足</p>
{% else %} <!--也是在if標籤結構裡面的-->
<p>條件都不成立,執行我吧</p>
{% endif %}
with 標籤
給一個複雜的變數起別名
{% with total=business.employees.count %}
{{ total }} <!--只能在with語句體內用-->
{% endwith %}
或者
{% with business.employees.count as total %}
{{ total }}
{% endwith %}
csrf_token 標籤
用於跨站請求偽造保護
在form表單裡面任何位置寫上。
工作原理:
1、在GET請求到form表單時,標籤{% csrf_token%}會被渲染成一個隱藏的input標籤,該標籤包含了由服務端生成的一串隨機字串,如下:
<input type="hidden" name="csrfmiddlewaretoken" value="dmFo...O5">
2、在使用form表單提交POST請求時,會提交上述隨機字串,服務端在接收到該POST請求時會對比該隨機字串,對比成功則處理該POST請求,否則拒絕,以此來確定客戶端的身份
例項:
<form action="" method="post">
{% csrf_token %}
使用者名稱:<input type="text">
密碼:<input type="password">
<input type="submit">
</form>
五、自定義過濾器和標籤
當內建的過濾器和標籤無法支援我們的需求時,就使用自定義標籤或過濾器
自定義過濾器
步驟:
1、在資料夾app01中建立子資料夾 templatetags (資料夾只能是templatetags)
2、在 templatetags 新建任意 .py 檔案,如 mytags.py,在該檔案中自定義過濾器或標籤。
內容如下
# mytags.py 檔案
from django import template # 匯入的模組
register = template.Library() # register 固定的名字 註冊器
# 自定義過濾器
@register.filter
def my_filter1(v1): # 不帶引數的
# 對 v1 的操作
v = v1 + '操作'
return v
"""
使用:HTML檔案中
{% load 檔名 %} --> 在HTML文件中必須先載入存有自定義過濾器和標籤的檔案
{{ value1|my_filter1 }} --> 無引數
把 value1 的值傳入給 v1 ,做處理後返回。
"""
@register.filter
def my_filter2(v1, v2): # 帶引數的過濾器(最多隻能帶兩個)
# 對 v1 v2 的操作
v = v1 + v2
return v
"""
使用:HTML檔案中
{% load 檔名 %} --> 在HTML文件中必須先載入存有自定義過濾器和標籤的檔案
{{ value1|my_filter1:value2 }} --> 有引數
把 value1 的值傳給 v1 ,引數 value2 傳給 v2 ,做處理後返回
"""
自定義標籤
步驟和自定義過濾器一樣:
# mytags.py 檔案
from django import template # 匯入的模組
register = template.Library() # register 固定的名字 註冊器
@register.simple_tag
def my_tag(v1, v2, v3): # 自定義的標籤可以定義多個引數
# 對傳入的引數處理
v = v1 + v2 + v3
return v
"""使用:HTML檔案中
{% load 檔名 %} --> 在HTML文件中必須先載入存有自定義過濾器和標籤的檔案
{% my_tag value1 value2 value3 %}
把 value1=v1 value2=v2 value3=v3 傳入標籤中,處理後返回。
"""
六、模板繼承
在Django模版引擎中最強大也是最複雜的部分就是模版繼承了。模版繼承可以讓您建立一個基本的 “骨架” 模版,它包含您站點中的全部元素,並且可以定義能夠被子模版覆蓋的 blocks 。
模板主要圍繞三種標籤的使用:include標籤、extends標籤、block標籤。
模板繼承之include標籤
include標籤也稱為元件
元件和外掛的簡單區別:
- 元件是提供某一完整功能的模組。
- 而外掛更傾向於封閉某一功能方法的函式。
作用:在一個HTML模板檔案中,引入或者重複使用另一個模板檔案的內容。
{% include '模板名稱' %}
例項:
把整個 test.html 模板引入到 index.html 模板中
<!-- test.html 檔案 -->
<div>
<ul>
<li>小楊</li>
<li>小明</li>
<li>鮑勃</li>
<li>艾倫</li>
</ul>
</div>
<!------------------------------------------------------------------------>
<!-- index.html 檔案 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
{% include 'test.html' %} <!-- 此處,當此檔案傳送給客戶端的時候,就變成了test.html檔案的內容了 -->
</div>
</body>
</html>
模板繼承之extends標籤、block標籤
作用:在一個HTML模板檔案中,引入或者重複使用另一個模板檔案的內容。
include 有的功能 extends 全都有,但是 extends 可以搭配一個block標籤,用於在繼承的基礎上增加新的內容
模板制定鉤子
{% block 鉤子名 %}
<!-- 另一HTML模板引入此模板時可以從此處填充自己的內容 -->
{% endblock 鉤子名 %}
新模板引入舊模板,並從舊模板鉤子處填充新內容
{% extends '模板名' %}
<!-- 用新內容完全覆蓋了父模板鉤子中的內容 -->
{% block 鉤子名 %}
<p> Hello World... </p>
{% endblock 鉤子名 %}
例項:
1、制定一個模板 base.html ,它定義了一個頁面上面的導航欄,和頁面左邊的選單欄,網頁中間由我們引入模板時自行填充自己的內容。
|---------------------|
| 導航欄 |
|-------|-------------|
| 菜 | |
| 單 | 自行填充的內容 |
| 欄 | |
|-------|-------------|
模板 base.html 檔案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.top {
height: 100px;
background-color: red;
}
.left {
height: 400px;
width: 20%;
background-color: aqua;
float: left;
}
.centre {
float: right;
height: 400px;
width: 80%;
background-color: green;
}
</style>
</head>
<body>
<div class="top">
<a href="">導航一</a>
<a href="">導航二</a>
<a href="">導航三</a>
<a href="">導航四</a>
</div>
<div class="counter">
<div class="left">
<p><a href="">選單一</a></p>
<p><a href="">選單二</a></p>
<p><a href="">選單三</a></p>
<p><a href="">選單四</a></p>
</div>
<div class="centre">
{% block centent %}
<ul>
<li>資訊1</li>
<li>資訊2</li>
<li>資訊3</li>
</ul>
<!-- 另一HTML模板引入此模板時可以從此處填充自己的內容 -->
{% endblock centent %}
</div>
</div>
</body>
</html>
2、index.html 模板引入base.html 模板,並在 base.html 模板鉤子處新增新內容。
{% extends 'base.html' %}
{% block centent %}
{{ block.super }} ————> 該變數會將父模板中 centent 中原來的內容繼承過來
<!--在繼承父模板內容的基礎上新增的標籤-->
<form action="" method="post">
{% csrf_token %}
使用者名稱:<input type="text">
密碼:<input type="password">
<input type="submit">
</form>
{% endblock centent %}
3、當啟動 Django 訪問 index.html 頁面時返回的內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.top {
height: 100px;
background-color: red;
}
.left {
height: 400px;
width: 20%;
background-color: aqua;
float: left;
}
.centre {
float: right;
height: 400px;
width: 80%;
background-color: green;
}
</style>
</head>
<body>
<div class="top">
<a href="">導航一</a>
<a href="">導航二</a>
<a href="">導航三</a>
<a href="">導航四</a>
</div>
<div class="counter">
<div class="left">
<p><a href="">選單一</a></p>
<p><a href="">選單二</a></p>
<p><a href="">選單三</a></p>
<p><a href="">選單四</a></p>
</div>
<div class="centre">
<!-- 此處被替換 -->
<form action="" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="WE..DF">
使用者名稱:<input type="text">
密碼:<input type="password">
<input type="submit">
</form>
</div>
</div>
</body>
</html>
總結:
- 標籤extends必須放在首行,base.html 中 block 越多控制性越強
- include 僅僅只是完全引用了其他模板檔案,而 extends 卻可以搭配 block 在引用的基礎上進行擴寫
- 變數 {{ block.super }} 可以重用父類的內容,然後再父類基礎上增加新內容,而不是完全覆蓋
- 在一個模板中不能出現重名的block標籤。
七、靜態檔案配置
在網站中我們需要用到大量的css、js、圖片等,這些都叫做靜態檔案。
關於Django中靜態檔案的配置,我們就需要在 settings 配置檔案裡面寫上這樣的內容:
1、例如在專案中建立一個 static_file 資料夾來存放靜態檔案。
注意:別名可以隨便寫名字,但是如果改了名字,別忘了如果前端頁面如果是通過 /別名/靜態檔案
呼叫靜態檔案的話,前端頁面的靜態檔案也要更改成一樣的
STATIC_URL = '/static/' # 別名
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static_file')
]
2、前端頁面引入靜態檔案
方式一:不推薦,別名如果有變化,所有應用別名的地方都需要改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/my.css">
</head>
<body>
<h1 class="c1" id="d1">點我就彈窗</h1>
<img src="/static/img/my.png" alt="">
<script src="/static/js/my.js"></script>
</body>
</html>
方式二:推薦,通過 load static 來找到別名,通過別名對映路徑的方式來獲取靜態檔案
標籤static會接收傳入的引數,然後這根據settings.py中變數STATIC_URL的值拼接出一個完整的路徑
{% load static %} <!-- 注意:必須先載入檔案static.py -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 注意:此處的static是一個定義在 static.py 中的一個標籤,名字與檔名一樣 -->
<link rel="stylesheet" href="{% static 'css/my.css' %}">
</head>
<body>
<h1 class="c1" id="d1">點我就彈窗</h1>
<img src="{% static 'img/my.png' %}" alt="">
<script src="{% static 'js/my.js' %}"></script>
</body>
</html>
方式三:get_static_prefix 標籤
和上面的效果一樣,不過只是用法不同。get_static_prefix 不能傳參,只能拼接,如下:
{% load static %} <!-- 注意:必須先載入檔案static.py -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% get_static_prefix %}css/my.css">
</head>
<body>
<h1 class="c1" id="d1">點我就彈窗</h1>
<img src="{% get_static_prefix %}img/my.png" alt="">
<script src="{% get_static_prefix %}js/my.js"></script>
</body>
</html>