Django2.X—Django模板引擎

Django模板引擎

Django內置的模板引擎包含模板上下文(亦可稱爲模板變量)、標籤和過濾器,各個功能說明如下:

  • 模板上下文是以變量的形式寫入模板文件,變量值由視圖函數或視圖類傳遞所得
  • 標籤是對模板上下文進行控制輸出,比如模板上下文的判斷和循環控制等。
  • 模板繼承隸屬標籤,它是將每個模板文件重複代碼抽取出來並寫在一個共用的模板文件中,其他模板文件通過繼承共用模板文件夾實現完整的網頁輸出。
  • 過濾器是對模板上下文進行操作處理,比如模板上下文的內容截取、替換或格式轉換等。

1、 模板上下文

模板上下文是模板中基本的組成單位,上下文的數據由視圖函數或視圖類傳遞。它以{{variable}}表示,variable是上下文名稱,它支持Python所有的數據類型,如字典、列表、元組、字符串、整型和實例化對象。上下文的數據格式不同,在模板裏使用方式也有所差異,如下所示:

# 假如variable1 = '字符串或整型'
<div>{{variable}}</div>
# 輸出"<div>字符串或整型</div>"

# 假如variable2={'name':'字典或實例化對象'}
<div>{{variable2.name}}</div>
# 輸出"<div>字典或實例化對象</div>"

# 假如variable3=['元組或列表']
<div>{{vaiable3}}</div>
# 輸出"<div>元組或列表</div>"

如果視圖沒有模板上下文傳遞數據或者模板上下文的某個屬性、索引下標不存在,Django會將其設爲空值。

2、 自定義標籤

標籤是對模板上下文進行控制輸出,它是以{% tag %}表示的,其中tag是標籤的名稱,Django內置了許多模板標籤,比如{% if %}(判斷標籤)、{% for %}(循環標籤)或{% url %}(路由標籤)等。
常用的內置標籤:

標籤 描述
{% if %} 遍歷輸出上下文的內容
{% for %} 對上下文進行條件判斷
{% csrf_token %} 生成csrf_token 的標籤,用於防護跨站請求僞造攻擊
{% url %} 引用路由配置的地址。生成相應的路由地址
{% wiht %} 將上下文重新命名
{% load %} 加載導入Django的標籤庫
{% static %} 讀取靜態資源的文件內容
{% extends xxx %} 模板繼承,xxx爲模板文件名,使當前模板繼承xxx模板
{% block xxx %} 重寫父類模板的代碼

在上述常用標籤中,每個標籤的使用方法都是各不相同,通過簡單的例子進一步瞭解標籤的使用方法,代碼如下:

# for標籤,支持嵌套,myList可爲列表、元組或某個對象
# item可自定義命名,代表當前循環的數據對象
# {% endfor %}是循環區域終止符,代表着區域的代碼由標籤for輸出
{% for item in myList %}
{{ item }}
{% endfor %}

# if標籤,支持嵌套
# 判斷條件與上下文之間使用空格隔開,否則程序會拋出異常
# {% endif %}與{% endfor %}的作用是相同的
{% if name=="Lily" %}
{{name}}
{% elif name=="Lucy" %}
{{name}}
{% else %}
{{name}}
{% endif %}

# url標籤
# 生成不帶變量的URL地址
<a href="{% url 'index' %}">首頁</a>
# 生成帶變量的URL地址
<a href="{% url 'page' 1 %}">第1頁</a>

# with標籤,與Python的with的語法的功能相同
# total=number無須空格隔開,否則拋出異常
{% with total=number %}
{{ total }}
{% endwith %}

# load標籤,導入靜態文件標籤庫staticfiles
# staticfiles來自settings.py的INSTALLED_APPS
{% load staticfiles %}

# static標籤,來自靜態文件標籤庫staticfiles
{% static "css/index.css" %}

在for標籤中,模板還提供了一些特殊的變量來獲取for標籤的循環信息,變量說明如下:

變量 描述
forloop.counter 獲取當前循環的索引,從1開始計算
forloop.counter0 獲取當前循環的索引,從0開始計算
forloop.revcounter 索引從最大數開始遞減,直到索引到1位置
forloop.revcounter0 索引從最大數開始遞減,直到索引到0位置
forloop.first 當遍歷的元素爲第一項時爲真
forloop.last 當遍歷的元素爲最後一項時爲真
forloop.parentloop 在嵌套的for循環中,獲取上層for循環的forloop

上述變量來自於forloop對象,該對象是在模板引擎for標籤時生成的,通過以下例子進一步瞭解forloop,例子如下:

{% for name in name_list %}
{% if forloop.counter == 1 %}
<span>這是第一次循環</span>
{% elifforloop.last %}
<span>這是最後一次循環</span>
{% else %}
<span>本次循環次數爲:{{forloop.counter}}</span>
{% endif %}
{% endfor %}

除了使用內置的模板標籤之外,還可以自定義模板標籤。 以MyDjango爲例,在項目的根目錄創建新的文件夾,文件夾名稱可稱自行命名,本示例命名爲mydefined;然後在該文件下創建初始化文件_init_.py和templatetags文件夾,其中templatetags文件夾的命名是固定不變的;最後在templatetags文件裏創建初始化文件_init_.py和自定義標籤文件mytags.py,項目的目錄結構如圖:
在這裏插入圖片描述
由於在項目的根目錄下創建了mydefined文件夾,因此在配置文件settings.py的屬性INSTALLED_APPS裏添加mydefined,否則Django在運行時無法加載mydefined文件夾的內容。配置信息如下:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'index',
    # 添加自定義模版標籤的文件夾
    'mydefined'
]

下一步在項目的mytags.py文件裏自定義標籤,我們將定義一個名爲reversal的標籤,它是將標籤裏的數據進行反轉處理,定義過程如下:

from django import template
# 創建模版對象
register = template.Library()

# 定義模版節點類
class ReversalNode(template.Node):
    def __init__(self, value):
        self.value = str(value)

    # 數據反轉處理
    def render(self, context):
        return self.value[::-1]

# 聲明並定義標籤
@register.tag(name='reversal')
# parse是解析器對象,token是被解析的對象
def do_reversal(parse, token):
    try:
        # tag_name是代表標籤名,即reversal
        # value是由標籤傳遞的數據
        tag_name, value = token.split_contents()
    except:
        raise template.TemplateSyntaxError('syntax')
    # 調用自定義的模板節點類
    return ReversalNode(value)

在mytags.py文件裏分別定義類ReversalNode和函數do_reversal,兩者實現功能說明如下:

  • 函數do_reversal經過裝飾器register.tag(name=‘reversal’)處理,這是讓函數執行模板標籤註冊,標籤名稱由裝飾器參數name進行命名,如果沒有設置參數name,就以函數名作爲標籤名稱。函數名沒有具體要求,一般以 “do_標籤名”“標籤名稱” 作爲命名規範。
  • 函數參數parse是解析對象,當Django運行時,它將所有標籤和過濾器進行加載並生成到parse對象,在解析模板文件裏面的標籤時,Django就會從parse對象查找對應的標籤信息。
  • 函數參數token是模板文件使用標籤時所傳遞的數據對象,主要包括標籤名和數據內容。
  • 函數do_reversal對參數token使用spilt_contents()方法(Django內置方法)進行取值處理,從中獲取數據value,並將value傳遞給自定義模板節點類ReversalNode。
  • 類ReversalNode是將value執行字符串反轉處理,並生成模板節點對象,用於模板引擎解析HTML語言。

爲了驗證自定義標籤reversal的功能,我們在index的urls.py、views.py和模板文件index.html裏編寫以下代碼:

# index的url.py
from django.urls import path
from .views import *
urlpatterns = [
    # 定義路由
    path('', index, name='index'),
]


# index的views.py
from django.shortcuts import render
def index(request):
    return render(request, 'index.html', locals())


# templates的index.html
{#導入自定義標籤文件mytags#}
{% load mytags %}
<!DOCTYPE html>
<html>
<body>
{% reversal 'Django' %}
</body>
</html>

在模板文件index.html中使用自定義標籤,必須使用{% load mytags %}將自定義標籤文件導入,告知模板引擎從哪裏查找自定義標籤,否則無法識別自定義標籤,並提示TemplateSyntaxError異常。
總結:

  • 自定義標籤需要在項目裏搭建目錄環境。
  • 在使用時需要在模板文件裏導入自定義標籤文件。

3、 模板繼承

模板繼承是通過模板標籤來實現的,其作用是將多個模板文件的共同代碼集中在一個新的模板文件中,然後各個模板可以直接調用新的模板文件,從而生成HTML網頁,這樣可以減少模板之間重複的代碼,範例如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
 <title>{{ title }}</title>
 </head>
<body>
	<a href="{% url "index:index" %}">首頁</a>
	<h1>Hello Django</h1>
</body>
</html>

上述代碼是一個完整的模板文件,一個完整的模板通常有<head>和<body>兩部分,而每個模板的<head>和<body>的內容都會有所不同,因此除了這兩部分的內容之外,可以將其他內容寫在共用模板文件裏。
以MyDjango爲例,在templates文件夾裏創建base.html文件,該文件作爲共用模板,代碼如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
{% block title %}
    <title>首頁</title>
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>

在base.html的代碼中看到,<title>寫在模板標籤{% block title %}{% endblock %}裏面,而<body>裏的內容改爲{% block title %}{% endblock %}。block標籤是爲其他模板文件調用時提供內容重寫的接口,body是對這個接口進行命名。在一個模板中可以添加多個block標籤,只要每個block標籤的命名不相同即可。接着在模板index.html中調用共用模板base.html,代碼如下:

{% extends "base.html" %}
{% block body %}
<a href="{% url 'index:index' %}">首頁</a>
<h1>Hello Django</h1>
{% endblock %}

模板index.html調用共用模板base.html的實質是由模板繼承實現的,調用步驟如下:

  • 在模板index.html中使用{% extends “base.html” %}來繼承模板base.html的所有代碼。
  • 通過使用標籤{% block title %}或{% block body %}來重寫模板base.html的網頁內容。
  • 如果沒有使用標籤block重寫共用模板內容,網頁內容將由共用模板提供,比如模板index.html沒有使用標籤{% block title %}重新定義<title>,那麼網頁標題內容應由模板base.html設置<title>提供。
  • 標籤block必須使用{% endblock %}結束block標籤。

從模板index.html看到,模板繼承魚Python的類繼承原理一致的,通過繼承方式使具有父類的功能和屬性,同時也可以通過重寫來實現複雜多變的開發需求。
結果展示:
在這裏插入圖片描述

4、 自定義過濾器

過濾器是對上下文的內容進行操作處理,如替換、反序和轉義等。通過處理器上下文可以將數據格式或內容轉化爲我們想要的顯示效果,而且相應減少視圖的代碼量。過濾器的使用方法如下:

{{ variable | filter }}

若上下文設有過濾器,則模板引擎在解析上下文時,首先由過濾器filter處理上下文variable,然後將處理後的結果進行解析並顯示在網頁上。variable代表模板上下文,管道符號"|"代表當前上下文使用過濾器,filter代表過濾器。單個上下文可以支持多個過濾器同時使用,例如:

{{ variable | filter | lower }}

在使用的過程中,有些過濾器還可以傳入參數,但僅支持傳入一個參數。帶參數的過濾器與參數之間使用冒號隔開,並且兩者之間不能留有空格,例如:

{{ variable | date:"D d M Y"}}

Django的內置過濾器可以在源碼(\django\template\defaultfilters.py)裏找到具體的定義過程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章