Django模板系統使用指南

Django自帶的模板系統雖然比不上專業的類似jinjia2那么自由的模板系統,但是對于我們新手來說也是夠用了,由于Django是一個強大且全面的大型Web框架,該有的都已經內置了,功能上不盡完美也有替代的方案,所以以后有機會再和大家說說如何替換默認自帶模板系統。

今天我們來聊一聊Django模板系統使用的方法,我盡量全面且系統的介紹使用方法,如果有遺漏或欠缺的地方,麻煩指正。

1.語句語法的使用

  • 變量或常量引用:{{ 變量或常量 }}
  • 基礎的語法使用:{% 語法 %}
  • 變量或常量別名:{% 舊名稱 as 新名稱 %}
  • 注釋的簡單用法:{# 注釋內容 #}

1.1 靜態文件引用:

<!--頁頭-->
{% load staticfiles %}

<!--使用-->
{% static "文件路徑" %}

1.2 相對地址引用:

{% url '應用名稱:url.py內定義的名字'  %}

注意:名稱后面可跟著參數,傳值方式為位置傳參(value1,value2)和關鍵詞傳參(value="1")。

1.3 變量或常量傳遞:

例如:我想根據網頁內容的不同顯示不同的標題。
做法:

# views.py
# -*- coding: utf-8 -*-
from django.shortcuts import render
 
def index(request):
    title = "標題1"
    return render(request, 'index.html', {'title ': title })

使用:

<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{title}}</title>
</head>
<body>
    <h1>我的第一個HTML頁面</h1>
    <p>我的第一個段落。</p>
</body>
</html>

而如果是字典呢?

# views.py
# -*- coding: utf-8 -*-
from django.shortcuts import render
 
def index(request):
    test_dict = {'name': '測試字典類型', 'content': '簡單示例'}
    return render(request, 'index.html', {'test_dict': test_dict})

使用(在模板中取字典的鍵是用 **. **(例如:test_dict.name),而不是我們認為的Python中的 test_dict['name']):

<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>網站標題</title>
</head>
<body>
    <h1>{{ test_dict.name }}</h1>
    <p>{{ test_dict.content}}</p>
</body>
</html>

特別注意:所有用到上下文傳遞的數據只能是字典類型,模板系統并不支持下標索引。

1.4 自定義模板標簽:

說明:本段參考《 追夢人物:10 - 頁面側邊欄:使用自定義模板標簽

有時候我們需要使用一些公共的數據,而如果每次都在視圖內寫獲取函數,那會導致我們寫很多重復代碼,所以Django為我們提供了自定義模板標簽。

簡單示例:

首先在我們的項目應用下創建一個 templatetags 文件夾。然后在這個文件夾下創建一個** __init__.py**文件,使這個文件夾成為一個 Python 包,之后在 templatetags\ 目錄下創建一個 get_data.py 文件,這個文件存放自定義的模板標簽代碼。

# get_data.py
from django import template

register = template.Library()

@register.simple_tag
def get_data_age():
    age = 10
    return age

使用:

<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>網站標題</title>
</head>
<body>
<!--導入自定義模板標簽-->
{% load get_data %}
<!--將函數獲取的值取名-->
{% get_data_age as age%}
    <h1>我的第一個HTML頁面</h1>
        <!--使用-->
    <p>我的年紀{{ age }}</p>
</body>
</html>

說明:這里我們首先導入 template 這個模塊,然后實例化了一個 template.Library 類,并將函數 get_recent_posts 裝飾為 register.simple_tag。這樣就可以在模板中使用語法 {% get_data_age %} 調用這個函數了。

注意: Django 1.9 后才支持 simple_tag 模板標簽,如果你使用的 Django 版本小于 1.9,你將得到一個錯誤。

2.通用模板的使用

很多網站的網頁會存在公共部分(即相同標簽內容,比如導航,底部等),所以Django將這部分內容做成block,減輕我們的工作量。

2.1 簡單使用方法:

首先在你的其他html文件同級目錄下新建一個html文件,名稱自定義,最好與公用部分含義一致,例如:test.html,下面我以這個名稱做示例。

完整的HTML頁面比如是這樣的:

<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>網站標題</title>
</head>
<body>
    <h1>我的第一個HTML頁面</h1>
    <p>我的第一個段落。</p>
</body>
</html>

我們把公共部分抽離出來,不同頁面不同部分做成block

提示:其中name為自定義名稱。

<!--test.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>網站標題</title>
</head>
<body>
    {% block name %}
    {% endblock name %}
</body>
</html>

然后我們就可以修改index.html的內容:

<!--index.html-->
{% extends 'test.html' %}
    {% block name %}
    {% endblock name %}

注意:“ Django 模板查找機制: Django 查找模板的過程是在每個 的 **templates **文件夾中找(而不只是當前應用 中的代碼只在當前的應用的 templates 文件夾中找)。各個應用的 templates 形成一個文件夾列表,Django 遍歷這個列表,一個個文件夾進行查找,當在某一個文件夾找到的時候就停止,所有的都遍歷完了還找不到指定的模板的時候就是 Template Not Found (過程類似于Python找包)。這樣設計有利當然也有弊,有利是的地方是一個應用可以用另一個應用的模板文件,弊是有可能會找錯了。所以我們使用的時候在 templates 中建立一個 應用同名的文件夾,這樣就好了。” -- 來自 《自強學堂-Django基礎教程

還有一個全內容引用:
{% include 'test1.html' %} :代表導入test1.html內所有內容到指定位置(可重復使用)。

3.邏輯控制的語法

3.1 if else 條件判斷:

注意:這里的if語句并沒有elif。

{% if 真/假 %}
  執行語句一 
{% else %}
  否則執行語句二
{% endif%}

3.2 for in 循環遍歷:

{% for 值 in 可迭代對象 %}
  執行語句一 
{% empty %}
  值為空時執行的語句
{% endfor%}

3.2.1 for in 循環內的控制變量

  • forloop.counter 索引從 1 開始算
  • forloop.counter0 索引從 0 開始算
  • forloop.revcounter 索引從最大長度到 1
  • forloop.revcounter0 索引從最大長度到 0
  • forloop.first 當遍歷的元素為第一項時為真
  • forloop.last 當遍歷的元素為最后一項時為真
  • forloop.parentloop 獲取上一層 for 循環的 forloop

例如:

{% for item in items%}
    {{ item }}{% if not forloop.last %}如果此次循環item為最后一個值,則item后面加上本段文字{% endif %} 
{% endfor %}

其他更多用法自己實驗。

3.3 ifequal/ifnotequal 值判斷是否相同:

注意:{% ifequal %}比較兩個值,如果相等,則顯示{% ifequal %}和{% endifequal %}之間的所有內容:
{% ifnotequal%} 自然就是不相等了。

{% ifequal 值1 值2%}
  執行語句一 
{% else %}
  否則執行語句二
{% endifequal %}

4.基礎的模板過濾

  • {{ bio | truncatewords:"30" }}:英文顯示前30個字
  • {{ bio | truncatechars:"30"}}:顯示前30個字
  • {{ pub_date | date:"F j, Y" }}:格式化
  • {{ 123|add:"5" }} :給value加上一個數值
  • {{ "AB'CD"|addslashes }} :單引號加上轉義號,一般用于輸出到javascript中
  • {{ "abcd"|capfirst }} :第一個字母大寫
  • {{ "abcd"|center:"50" }} :輸出指定長度的字符串,并把值對中
  • {{ "123spam456spam789"|cut:"spam" }} :查找刪除指定字符串
  • {{ value|date:"F j, Y" }} :格式化日期
  • {{ value|default:"(N/A)" }} :值不存在,使用指定值
  • {{ value|default_if_none:"(N/A)" }} :值是None,使用指定值
  • {{ 列表變量|dictsort:"數字" }} :排序從小到大
  • {{ 列表變量|dictsortreversed:"數字" }} :排序從大到小
  • {{% if 92|divisibleby:"2" %} 判斷是否整除指定數字
  • {{ string|escape }} :轉換為html實體
  • {{ 21984124|filesizeformat }} :以1024為基數,計算最大值,保留1位小數,增加可讀性
  • {{ list|first }} :返回列表第一個元素
  • {{ "ik23hr&jqwh"|fix_ampersands }} :&轉為&
  • {{ 13.414121241|floatformat }} :保留1位小數,可為負數,幾種形式
  • {{ 13.414121241|floatformat:"2" }} :保留2位小數
  • {{ 23456 |get_digit:"1" }} :從個位數開始截取指定位置的1個數字
  • {{ list|join:", " }} :用指定分隔符連接列表
  • {{ list|length }} :返回列表個數
  • {% if 列表|length_is:"3" %} 列表個數是否指定數值
  • {{ "ABCD"|linebreaks }} :用新行用<p> 、 <br /> 標記包裹
  • {{ "ABCD"|linebreaksbr }} :用新行用<br /> 標記包裹
  • {{ 變量|linenumbers }} :為變量中每一行加上行號
  • {{ "abcd"|ljust:"50" }} :把字符串在指定寬度中對左,其它用空格填充
  • {{ "ABCD"|lower }} :小寫
  • {% for i in "1abc1"|make_list %}ABCDE,{% endfor %} 把字符串或數字的字符個數作為一個列表
  • {{ "abcdefghijklmnopqrstuvwxyz"|phone2numeric }} :把字符轉為可以對應的數字??
  • {{ 列表或數字|pluralize }} :單詞的復數形式,如列表字符串個數大于1,返回s,否則返回空串
  • {{ 列表或數字|pluralize:"es" }} :指定es
  • {{ 列表或數字|pluralize:"y,ies" }} :指定ies替換為y
  • {{ object|pprint }} :顯示一個對象的值
  • {{ 列表|random }} :返回列表的隨機一項
  • {{ string|removetags:"br p div" }} :刪除字符串中指定html標記
  • {{ string|rjust:"50" }} :把字符串在指定寬度中對右,其它用空格填充
  • {{ 列表|slice:":2" }} :切片
  • {{ string|slugify }} :字符串中留下減號和下劃線,其它符號刪除,空格用減號替換
  • {{ 3|stringformat:"02i" }} :字符串格式,使用Python的字符串格式語法
  • {{ "E<A>A</A>B<C>C</C>D"|striptags }} :剝去[X]HTML語法標記
  • {{ 時間變量|time:"P" }} :日期的時間部分格式
  • {{ datetime|timesince }} :給定日期到現在過去了多少時間
  • {{ datetime|timesince:"other_datetime" }} :兩日期間過去了多少時間
  • {{ datetime|timeuntil }} :給定日期到現在過去了多少時間,與上面的區別在于2日期的前后位置。
  • {{ datetime|timeuntil:"other_datetime" }} :兩日期間過去了多少時間
  • {{ "abdsadf"|title }} :首字母大寫
  • {{ "A B C D E F"|truncatewords:"3" }} :截取指定個數的單詞
  • {{ "<a>1<a>1<a>1</a></a></a>22<a>1</a>"|truncatewords_html:"2" }} :截取指定個數的html標記,并補完整</ul>
  • {{ list|unordered_list }}</ul>多重嵌套列表展現為html的無序列表
  • {{ string|upper }} :全部大寫
  • {{ link|urlencode }} :url編碼
  • {{ string|urlize }} :將URLs由純文本變為可點擊的鏈接。(沒有實驗成功)
  • {{ string|urlizetrunc:"30" }} :同上,多個截取字符數。(同樣沒有實驗成功)
  • {{ "B C D E F"|wordcount }} :單詞數
  • {{ "a b c d e f g h i j k"|wordwrap:"5" }} :每指定數量的字符就插入回車符
  • {{ boolean|yesno:"Yes,No,Perhaps" }} :對三種值的返回字符串,對應是 非空,空,None

... 歡迎補充完善。

5.涉及的其他知識

5.1 自定義過濾器:

其實這里和之前1.4的自定義模板標簽差不多,都是定義一個函數:

例如:這里我定義一個獲取傳入值前5位字符的過濾器

做法:同樣是那個get_data.py文件

# get_data.py
from django import template

register = template.Library()

@register.filter(name='truncate_filter')
def truncate_chars(value):
    if value.__len__() > 5:
        return '%s......'% value[0:5]
    else:
        return value

如果沒有使用name參數,django默認會將函數名作為name參數的值,所以下面的代碼和上面的代碼作用相同。

# get_data.py
from django import template

register = template.Library()

@register.filter
def truncate_chars(value):
    if value.__len__() > 5:
        return '%s......'% value[0:5]
    else:
        return value

說明:Library.filter(name,function,is_safe=False,needs_autoescape=False,excepts_localtime=False)函數默認需要兩個參數,name是裝飾器的名稱(字符串類型),function是函數名。

后面三個參數可以參考 官方文檔。這部分內容過于繁雜,一篇文章可能說不完,我暫時也并沒有用到,所以不做過多闡述。

用法:

<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>網站標題</title>
</head>
<body>
<!--導入自定義模板標簽-->
{% load get_data %}
    <h1>我的第一個HTML頁面</h1>
        <!--使用-->
    <p>我的年紀{{ "123456789"|truncate_chars}}</p>
</body>
</html>

這里只是做一個示例,你自己可以定義更強大的過濾器,畢竟我們缺少的只是想象力。

end

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容