1、DTL模板標籤
在for循環中,DTL提供了一些變量可供使用。
forloop.counter: 當前循環的下標。以1作爲起始值。
forloop.counter0: 當前循環的下標。以0作爲起始值。
forloop.revcounter: 當前循環的反向下標值。比如列表有5個元素,那麼第一次遍歷這個屬性是等於5,第二次是4,以此類推。並且是以1作爲最後一個元素的下標。
forloop.revcounter0: 類似於forloop.revcounter。不同的是最後一個元素的下標是從0開始。
forloop.first: 是否是第一次遍歷。
forloop.last: 是否是最後一次遍歷。
forloop.parentloop: 如果有多個循環嵌套,那麼這個屬性代表的是上一級的for循環。
for…in…empty標籤:這個標籤使用跟for…in…是一樣的,只不過是在遍歷的對象如果沒有元素的情況下,會執行empty中的內容。
{% for person in persons %}
<li>{{ person }}</li>
{% empty %}
暫時還沒有任何人
{% endfor %}
注意:在for循環中,break,continue語句是用不了的。
1. url標籤
url標籤:在模版中,我們經常要寫一些url,比如某個a標籤中需要定義href屬性。當然如果通過硬編碼的方式直接將這個url寫死在裏面也是可以的。但是這樣對於以後項目維護可能不是一件好事。因此建議使用這種反轉的方式來實現,類似於django中的reverse一樣。
<a href="{% url 'book:list' %}">圖書列表頁面</a>
如果url反轉的時候需要傳遞參數,那麼可以在後面傳遞。但是參數分位置參數和關鍵字參數。位置參數和關鍵字參數不能同時使用。
# path部分
path('detail/<book_id>/',views.book_detail,name='detail')
# url反轉,使用位置參數
<a href="{% url 'book:detail' 1 %}">圖書詳情頁面</a>
# url反轉,使用關鍵字參數
<a href="{% url 'book:detail' book_id=1 %}">圖書詳情頁面</a>
如果想要在使用url標籤反轉的時候要傳遞查詢字符串的參數,那麼必須要手動在在後面添加。
<!-- ?page=1是字符串拼接 -->
<a href="{% url 'book:detail' book_id=1 %}?page=1">圖書詳情頁面</a>
如果需要傳遞多個參數,那麼通過空格的方式進行分隔。
<!-- 傳遞多個參數使用空格分離 -->
<a href="{% url 'book:detail' book_id=1 page=2 %}">圖書詳情頁面</a>
with標籤
<!-- with語句 -->
{% with name=person.0 %}
{{ name }}
{% endwith %}
<!-- with語句 -->
{% with person.0 as name %}
{{ name }}
{% endwith %}
autoescape 自動轉義標籤
視圖文件:book/views.py,傳遞參數到前端頁面進行渲染:
def book_detail(request):
context = {
"username": "12345",
"book": ["python", "java", "php"],
"books": ("python", "java", "php"),
"info": {
"name": "xxxxx",
"url": "<a href='https://wwww.baidu.com'>百度</a>", # 鏈接渲染到前端會因爲源碼中的render_to_string方法變成字符串
},
# 傳遞類
"person": Person("ch")
}
# 注意第一個參數request要有 # render在源碼中封裝了render_to_string和HttpResponse
return render(request, "book_detail.html", context=context)
前端頁面渲染book_detail.html:
<!--info中的鏈接會自動轉換成字符串,自動轉義-->
{{info.url}}
<!-- 處理後的鏈接可以正常顯示,關閉自動轉義, off關閉,on打開 -->
{% autoescape off %}}
{{info.url}}
{% endautoescape %}}
更多標籤 : https://docs.djangoproject.com/en/2.0/ref/templates/builtins/
創建新的Django項目:
2、模版常用過濾器
在模版中,有時候需要對一些數據進行處理以後才能使用。一般在Python中我們是通過函數的形式來完成的。而在模版中,則是通過過濾器來實現的。過濾器使用的是|來使用。
add
將傳進來的參數添加到原來的值上面。這個過濾器會嘗試將值和參數轉換成整形然後進行相加。如果轉換成整形過程中失敗了,那麼會將值和參數進行拼接。如果是字符串,那麼會拼接成字符串,如果是列表,那麼會拼接成一個列表。
{{ value|add:"2" }}
如果value是等於4,那麼結果將是6。如果value是等於一個普通的字符串,比如abc,那麼結果將是abc2。
實例如下:
from django.shortcuts import render
from django.template import defaultfilters
def index(request):
context = {
"num": 2,
"str": 'abc',
}
return render(request, 'index.html', context=context)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>測試</h1>
<p> 首頁</p>
<!-- 前端頁面int類型加1操作 -->
<p>{{ num|add:"1" }}</p>
<!-- 前端頁面str類型加1操作 -->
<p>{{ str|add:"1" }}</p>
<!-- 前端頁面str類型加字符串操作 -->
<p>{{ str|add:"xxxxx" }}</p>
</body>
</html>
列表相加相當於列表拼接。
cut
移除值中所有指定的字符串。類似於python中的replace(args,"")。
{{ value|cut:" " }}
前端頁面渲染如下:
date
將一個日期按照指定的格式,格式化成字符串。
# 數據
context = {
"birthday": datetime.now()
}
# 模版
{{ birthday|date:"Y/m/d" }}
<!-- date使用 -->
<p>{{ birthday }}</p>
<p>{{ birthday|date:"Y/m/d" }}</p>
<p>{{ birthday|date:"Y/m/d H:i:s" }}</p>
default
如果值被評估爲False。比如[],"",None,{}等這些在if判斷中爲False的值,都會使用default過濾器提供的默認值。
{{ value|default:"nothing" }}
如果value是等於一個空的字符串。比如"",那麼以上代碼將會輸出nothing。
<!-- default使用 -->
<p>{{ info|default:"暫時沒有設置簽名" }}</p>
上面代碼中info如果有值,會顯示views.py中傳輸過來的值,如果沒有,會顯示default:“暫時沒有設置簽名”。
first
返回列表/元組/字符串中的第一個元素。
{{ value|first }}
last
返回列表/元組/字符串中的最後一個元素。
{{ value|last }}
def index(request):
context = {
"num": 2,
"str": 'abc',
"birthday": datetime.now(),
"info": "個性簽名",
"l1": [1, 2, 3, 4, 5, 6, 7, 8],
"z1": ("1", "2", "3", "4"),
}
return render(request, 'index.html', context=context)
index.html文件中渲染:
<p>{{ l1|first }}</p>
<p>{{ l1|last }}</p>
<p>{{ z1|first }}</p>
<p>{{ z1|last }}</p>
floatformat
使用四捨五入的方式格式化一個浮點類型。如果這個過濾器沒有傳遞任何參數。那麼只會在小數點後保留一個小數,如果小數後面全是0,那麼只會保留整數。當然也可以傳遞一個參數,標識具體要保留幾個小數。
<!-- ul標籤是無序列表標籤 ,顯示結果爲 34.3
34.4
34.353 -->
<ul>
<li>{{ 34.32|floatformat }}</li>
<li>{{ 34.35|floatformat }}</li>
<li>{{ 34.353333|floatformat:3}}</li>
</ul>
join
類似與Python中的join,將列表/元組/字符串用指定的字符進行拼接.
{{ value|join:"/" }}
如果value是等於[‘a’,‘b’,‘c’],那麼以上代碼將輸出a/b/c。
length
獲取一個列表/元組/字符串/字典的長度。
{{ value|length }}
如果value是等於[‘a’,‘b’,‘c’],那麼以上代碼將輸出3。如果value爲None,那麼以上將返回0。
lower
將值中所有的字符全部轉換成小寫。
{{ value|lower }}
upper
類似於lower,只不過是將指定的字符串全部轉換成大寫。
random
在被給的列表/字符串/元組中隨機的選擇一個值。
{{ value|random }}
safe
標記一個字符串是安全的。也即會關掉這個字符串的自動轉義。
<!-- 標記字符串是安全的,相當於關閉自動轉義功能 -->
{{value|safe}}
如果value是一個不包含任何特殊字符的字符串,比如這種,那麼以上代碼就會把字符串正常的輸入。如果value是一串html代碼,那麼以上代碼將會把這個html代碼渲染到瀏覽器中。
slice
類似於Python中的切片操作。
{{ some_list|slice:"2:" }} 從第2個元素到最後的元素
striptags
刪除字符串中所有的html標籤。
{{ value|striptags }}
truncatechars
如果給定的字符串長度超過了過濾器指定的長度。那麼就會進行切割,並且會拼接三個點來作爲省略號。
{{ value|truncatechars:5 }}
更多可以查看Django源碼
from django.template import defaultfilters,defaulttags
3、模版結構優化
引入模版
有時候一些代碼是在許多模版中都用到的。如果我們每次都重複的去拷貝代碼那肯定不符合項目的規範。一般我們可以把這些重複性的代碼抽取出來,就類似於Python中的函數一樣,以後想要使用這些代碼的時候,就通過include包含進來。這個標籤就是include。
# header.html
<p>我是header</p>
# footer.html
<p>我是footer</p>
# main.html
{% include 'header.html' %}
<p>我是main內容</p>
{% include 'footer.html' %}
include標籤尋找路徑的方式。也是跟render渲染模板的函數是一樣的。
默認include標籤包含模版,會自動的使用主模版中的上下文,也即可以自動的使用主模版中的變量。如果想傳入一些其他的參數,那麼可以使用with語句。
# header.html
<p>用戶名:{{ username }}</p>
# main.html
{% include "header.html" with username='xxx' %}
<!-- with定義名稱進行顯示 -->
模板繼承
在前端頁面開發中。有些代碼是需要重複使用的。這種情況可以使用include標籤來實現。也可以使用另外一個比較強大的方式來實現,那就是模版繼承。模版繼承類似於Python中的類,在父類中可以先定義好一些變量和方法,然後在子類中實現。模版繼承也可以在父模版中先定義好一些子模版需要用到的代碼,然後子模版直接繼承就可以了。並且因爲子模版肯定有自己的不同代碼,因此可以在父模版中定義一個block接口,然後子模版再去實現。
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="{% static 'style.css' %}" />
<title>{% block title %}
我的站點
{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">首頁</a></li>
<li><a href="/blog/">博客</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
這個是父模版,我們取名叫做base.html,定義好一個簡單的html骨架,然後定義好兩個block接口,讓子模版來根據具體需求來實現。子模板然後通過extends標籤來實現.
<!-- 繼承父模板的信息 -->
{% extends "base.html" %}
{% block title %}
博客列表
{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
模板繼承注意點
- extends標籤必須放在模版的第一行。
- 子模板中的代碼必須放在block中,否則將不會被渲染。
- 如果在某個block中需要使用父模版的內容,那麼可以使用{{block.super}}來繼承。比如上例,{%block title%},如果想要使用父模版的title,那麼可以在子模版的title block中使用{{ block.super }}來實現。
- 在定義block的時候,除了在block開始的地方定義這個block的名字,還可以在block結束的時候定義名字。比如{% block title %}{% endblock title %}。這在大型模版中顯得尤其有用,能讓你快速的看到block包含在哪裏。
- 子模板中的代碼,如果沒有放在{%block %}中,不會被渲染顯示出來。
4、加載靜態文件
在一個網頁中,不僅僅只有一個html骨架,還需要css樣式文件,js執行文件以及一些圖片等。因此在DTL中加載靜態文件是一個必須要解決的問題。在DTL中,使用static標籤來加載靜態文件。要使用static標籤,首先需要{% load static %}。
步驟如下:
- 1.首先確保django.contrib.staticfiles已經添加到settings.INSTALLED_APPS中。(默認已經添加)
- 2.確保在settings.py中設置了STATIC_URL。(默認創建了)
- 3.在已經安裝了的app下創建一個文件夾叫做static,然後再在這個static文件夾下創建一個當前app的名字的文件夾,再把靜態文件放到這個文件夾下。
默認添加了django.contrib.staticfiles
默認創建了STATIC_URL
創建static文件夾:
注意:爲什麼在app下創建一個static文件夾,還需要在這個static下創建一個同app名字的文件夾呢?
原因是如果直接把靜態文件放在static文件夾下,那麼在模版加載靜態文件的時候就是使用logo.jpg,如果在多個app之間有同名的靜態文件,這時候可能就會產生混淆。而在static文件夾下加了一個同名app文件夾,在模版中加載的時候就是使用app/logo.jpg,這樣就可以避免產生混淆。
第四步如下:
- 4.如果有一些靜態文件是不和任何app掛鉤的。那麼可以在settings.py中添加STATICFILES_DIRS,以後DTL就會在這個列表的路徑中查找靜態文件。
settings.py
# 指定靜態文件目錄
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
- 5.在模版中使用load標籤加載static標籤。比如要加載在項目的static文件夾下的style.css的文件。
{% load static %}
<link rel="stylesheet" href="{% static 'style.css' %}">
- 6.如果不想每次在模版中加載靜態文件都使用load加載static標籤,那麼可以在
settings.py
中的TEMPLATES/OPTIONS
添加'builtins':['django.templatetags.static']
,這樣以後在模版中就可以直接使用static標籤,而不用手動的load了。
settings.py:這樣設置會在加載靜態資源文件的路徑前加上/static/
路徑
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 模板路徑設置
'APP_DIRS': True,
'OPTIONS': {
# 不想每次在模版中加載靜態文件都使用load加載static標籤,以後在模版中就可以直接使用static標籤,而不用手動的load了
'builtins':['django.templatetags.static'],
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
這樣在模版中就可以直接使用static標籤,而不用手動的load了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 加載靜態資源文件中的css文件 -->
<link rel="stylesheet" href="{% static 'index.css' %}">
</head>