天天看點

初識Django(六):模版語言

其實我接觸過的web架構也就Java下的jsp和Python下的web.py和django、flask,但是他們都有類似模版語言的存在,有的是像Django一樣專門的創造,有的是簡單的在html文檔裡嵌入程式設計語句。但是毋庸置疑,這些“模版語言”是讓html檔案變得動态的根源。

模版語言定義(Django Template Language, DTL)

Django的模版語言十分簡明,很容易就能學會。我們用幾個判斷句來給模版語言定義。

-1 所有使用了模版語言的html檔案被我們稱為模版。

-2 在模版語言中,{% 語句 %}、{{ 輸出 }}、{# 注釋 #}。也就是說前者括号内的内容會被django執行,後者直接被運算後寫在檔案的相應位置上。

-3 在模版語言中,我們的變量可以使用|(過濾器)和.運算符,我們的語句可以用來載入内容或使用for/if/block/extends/url等标簽。不能直接運作python語言,這點要謹記。

{{ 輸出 }}

1 View與Template的互動

模版由視圖渲染并傳給用戶端,使用render函數。當模版中需要資料時,我們向render函數傳入同鍵名的字典。render函數的介紹在上一部分。

2 .運算符

DTL中的點運算符按照字典->對象->清單/元組查詢,當以上查詢都不成立的時候傳回空字元串。也就是說,如果你在前端傳入了一個數組a=[1,2,…],前端模版内你對其的通路應為a.1、a.2…

例1 view傳值:

示例項目根路徑下urls.py裡urlpatterns添加:

path("thirdurl",views.third)

子app helloworld下views.py:

def third(request):

if(request.method=="GET"):

dictionary={"key1":"1","key2":[1,2,3,4],"key3":{"a":"a","b":"b"}}

return render(request,"我的html.html",dictionary)

子app helloworld下檔案夾templates下我的html.html:

<!doctype html>

<html>

<head></head>

<body>

{{key1}}

{{key2.0}}

{{key3.a}}

</body>

</html>

項目下打開指令行runserver在127.0.0.1:8000下運作django,輸入127.0.0.1:8000/thirdurl,可以看到傳回了1 1 a。

3 |運算符與過濾器

過濾器可以被視為專門用來處理模版資料的python函數,在模版中,我們通過|運算符使用過濾器。Django内置了很多過濾器,這些可以在網上搜到,我們也可以自己制作過濾器。

-過濾器在使用之前需要使用{% load 過濾器檔案名 %}導入。

-過濾器檔案預設放在app目錄下templatetags檔案夾下。

-過濾器檔案中定義的函數即是過濾器,函數前要加上@register.filter(name="過濾器在模版中的名字"),整個檔案前要加上兩行:from django import template register=template.Library()。

例2 使用django自帶的過濾器:

示例項目根路徑下urls.py裡urlpatterns添加:

path("fourthurl",views.fourth)

子app helloworld下views.py:

def fourth(request):

if(request.method=="GET"):

dictionary={"key1":"1"}

return render(request,"我的html.html",dictionary)

子app helloworld下檔案夾templates下我的html.html:

<!doctype html>

<html>

<head></head>

<body>

{{key1.1|default:"不存在"}}

</body>

</html>

過濾器default為django自帶的過濾器,功能為在傳回空串時替代為後面的字元串。這個過濾器不需要導入(但是不是所有自帶的過濾器都不要)。項目下打開指令行runserver在127.0.0.1:8000下運作django,輸入127.0.0.1:8000/thirdurl,可以看到傳回了“不存在”,因為key1.1找不到值。

例3 一個小例子,自建過濾器:

子app helloworld下檔案夾templatetags檔案夾下建立block1.py:

from django import template

register=template.Library()

@register.filter(name="_reverse")#這個過濾器翻轉list

def _reverse(arg):

return reversed(arg)

在模版檔案中這麼引用:

<!doctype html>

<html>

<head></head>

<body>

{% load block1 %}

{{arg1|_reverse}}

</body>

</html>

{% 語句 %}

1 load語句

load語句用來載入自定義标簽或過濾器檔案,比如大名鼎鼎的{% load static %}。

# load static與 static ‘’

{% load static %}載入了static标簽,{% static ‘檔案路徑’ %}用于加載靜态檔案。

很多人把static标簽說的玄之又玄,其實不然。在沒有額外設定的情況下,django會去app目錄下的static目錄下尋找static引号裡字元串為路徑的檔案。(關于這些靜态檔案存放請參考我之前講的模版檔案的存放,請仔細思考django尋找檔案的順序和檔案的儲存順序,如果你直接随意存儲檔案,當其重名時django隻會傳回第一個查找的,這裡沒有對于app的就近原則)

-如果想要修改static目錄的名字,請修改settings.py檔案下的STATIC_URL。(根據url的解析規則你應該能意會這個變量定義了什麼)

-如果你的static不想放在app目錄下,可以在settings.py檔案下添加STATICFILES_DIRS變量,将其值設為你設定的static檔案夾,例如STATICFILES_DIRS= (os.path.join(BASE_DIR, "static"),),則靜态檔案夾為項目目錄下的static檔案夾。

2 for語句和if語句

DTL中的for語句和if語句的使用與python中相同,但是書寫方式有所不同。

{% for 表達式 %}内容{% endfor %} for語句

{% if 表達式 %}内容{% endif %} if語句

你可能注意到了兩個語句之間我寫的是内容而不是語句,事實上裡面也可以寫html标簽。不要想當然。

3 block語句

block語句擴住的内容可以被覆寫。我們通過引用模版并覆寫其中的block完成模版代碼的重用,如果不覆寫塊中的内容就是父模版中塊的内容。(可以想象一個父類和重寫父類方法的子類)這個特性可以很好的用于節省模版的編寫時間,也可以讓模版層次分明。

{% block 名稱 %}内容{% endblock 名稱 %} block語句

{% extends ‘模版檔案名稱’ %} 引用模版檔案

例4 覆寫block及引用static

項目app helloworld目錄下模版檔案夾下建立 父模版.html:

<!doctype html>

<html>

<head></head>

<body>

{% block myblock1 %}

<p>父内容</p>

{% endblock myblock1 %}

</body>

</html>

同目錄建立 子模版.html:

{% extends ‘父模版.html’ %}

{% block myblock1 %}

<p>子内容</p>

{% endblock myblock1 %}

很明顯,如果你的項目渲染了子模版,那麼會出現“子内容”。

{# 注釋 #}

關于這個注釋隻有一個需要注意的。Html檔案的注釋還會出現在檔案内,隻不過不被呈現出來,而DTL的注釋在渲染模版的時候就會被剔除。

關于DTL的一些思考

相比于直接在模版檔案中嵌入python語句,DTL顯得更加高明。因為它不但簡潔,而且從架構編寫者的方面就嚴格遵循了MTV模式,不需要使用架構者特意去注意這些。這就像“帶上腳鐐的舞蹈”,是有限制的自由,但是也更美。

Tips:本文裡涉及DTL的語句和标簽是等價的。