Python Django基礎教程(二)(模板templatetags)

HuangZhang_123發表於2017-04-20

Django版本:1.11
作業系統:Windows
歡迎加入學習交流QQ群:657341423


模板的使用:
模板是一個文字,用於分離文件的表現形式和內容。 模板定義了佔位符以及各種用於規範文件該如何顯示的各部分基本邏輯(模板標籤)。 模板通常用於產生HTML,但是Django的模板也能產生任何基於文字格式的文件。
模版大致結構:

<html>
<head><title>Ordering notice</title></head>
<body>
<h1>Ordering notice</h1>
<p>Dear {{ person_name }},</p>
<p>Thanks for placing an order from {{ company }}. It's scheduled to
ship on {{ ship_date|date:"F j, Y" }}.</p>
<p>Here are the items you've ordered:</p>
<ul>
{% for item in item_list %}
    <li>{{ item }}</li>
{% endfor %}
</ul>
{% if ordered_warranty %}
    <p>Your warranty information will be included in the packaging.</p>
{% else %}
    <p>You didn't order a warranty, so you're on your own when
    the products inevitably stop working.</p>
{% endif %}
<p>Sincerely,<br />{{ company }}</p>
</body>
</html>

用兩個大括號括起來的文字(例如 {{ person_name }} )稱為 變數(variable) 。這意味著在此處插入指定變數的值。

被大括號和百分號包圍的文字(例如 {% if ordered_warranty %} )是 模板標籤(template tag) 。標籤(tag)定義比較明確,即: 僅通知模板系統完成某些工作的標籤。

這個例子中的模板包含一個for標籤( {% for item in item_list %} )和一個if 標籤({% if ordered_warranty %} )

for標籤類似Python的for語句,可讓你迴圈訪問序列裡的每一個專案。 if 標籤,正如你所料,是用來執行邏輯判斷的。 在這裡,tag標籤檢查ordered_warranty值是否為True。如果是,模板系統將顯示{% if ordered_warranty %}和{% else %}之間的內容;否則將顯示{% else %}和{% endif %}之間的內容。{% else %}是可選的。

就是通俗一點說, {{xxx}}這個為變數。{% %} 為語法使用。在整體上模版的結構就是如此。

瞭解到模版的大致結構,再瞭解一下模版標籤


if/else
只能判斷True 和False
{% if %} 標籤檢查(evaluate)一個變數,如果這個變數為真(即,變數存在,非空,不是布林值假),系統會顯示在 {% if %} 和 {% endif %} 之間的任何內容,例如:

{% if today_is_weekend %}
    <p>Welcome to the weekend!</p>
{% endif %}

{% else %} 標籤是可選的:

{% if today_is_weekend %}
    <p>Welcome to the weekend!</p>
{% else %}
    <p>Get back to work.</p>
{% endif %}

{% if %} 標籤接受 and , or 或者 not 關鍵字來對多個變數做判斷 ,或者對變數取反( not ),但不允許在同一個標籤中同時使用 and 和 or ,因為邏輯上可能模糊的。


for

<ul>
{% for athlete in athlete_list %}
    <li>{{ athlete.name }}</li>
{% endfor %}
</ul>

給標籤增加一個 reversed 使得該列表被反向迭代:

{% for athlete in athlete_list reversed %}
...
{% endfor %}

可以巢狀使用 {% for %} 標籤

在執行迴圈之前先檢測列表的大小是一個通常的做法,當列表為空時輸出一些特別的提示。

{% if athlete_list %}
    {% for athlete in athlete_list %}
        <p>{{ athlete.name }}</p>
    {% endfor %}
{% else %}
    <p>There are no athletes. Only computer programmers.</p>
{% endif %}

因為這種做法十分常見,所以for 標籤支援一個可選的{% empty %} 分句,通過它我們可以定義當列表為空時的輸出內容 下面的例子與之前那個等價:

{% for athlete in athlete_list %}
    <p>{{ athlete.name }}</p>
{% empty %}
    <p>There are no athletes. Only computer programmers.</p>
{% endfor %}

在每個{% for %}迴圈裡有一個稱為forloop 的模板變數
forloop.counter 總是一個表示當前迴圈的執行次數的整數計數器。 這個計數器是從1開始的,所以在第一次迴圈時 forloop.counter 將會被設定為1。
forloop.counter0 類似於 forloop.counter ,但是它是從0計數的。 第一次執行迴圈時這個變數會被設定為0。6
forloop.revcounter 是表示迴圈中剩餘項的整型變數。 在迴圈初次執行時 forloop.revcounter 將被設定為序列中項的總數。 最後一次迴圈執行中,這個變數將被置1。
forloop.revcounter0 類似於 forloop.revcounter ,但它以0做為結束索引。 在第一次執行迴圈時,該變數會被置為序列的項的個數減1。
forloop.first 是一個布林值,如果該迭代是第一次執行,那麼它被置為````在下面的情形中這個變數是很有用的
forloop.last 是一個布林值;在最後一次執行迴圈時被置為True。
forloop.parentloop 是一個指向當前迴圈的上一級迴圈的 forloop 物件的引用(在巢狀迴圈的情況下)。 例子在此:

{% for country in countries %}
    <table>
    {% for city in country.city_list %}
        <tr>
        <td>Country #{{ forloop.parentloop.counter }}</td>
        <td>City #{{ forloop.counter }}</td>
        <td>{{ city }}</td>
        </tr>
    {% endfor %}
    </table>
{% endfor %}

forloop 變數僅僅能夠在迴圈中使用。 在模板解析器碰到{% endfor %}標籤後,forloop就不可訪問了。


ifequal/ifnotequal
對比兩個值是否相對,ifequal相等,ifnotequal不相等。只有模板變數,字串,整數和小數可以作為 {% ifequal %} 標籤的引數。其他任何型別,例如Python的字典型別、列表型別、布林型別,不能用在 {% ifequal %} 中。
下面的例子比較兩個模板變數 user 和 currentuser :

{% ifequal user currentuser %}
    <h1>Welcome!</h1>
{% endifequal %}

引數可以是硬編碼的字串,隨便用單引號或者雙引號引起來,所以下列程式碼都是正確的:

{% ifequal section 'sitenews' %}
    <h1>Site News</h1>
{% endifequal %}

和 {% if %} 類似, {% ifequal %} 支援可選的 {% else%} 標籤


註釋
就像HTML或者Python,Django模板語言同樣提供程式碼註釋。 註釋使用 {# #} :

{# This is a comment #}

如果要實現多行註釋,可以使用{% comment %} 模板標籤,就像這樣:

{% comment %}
This is a
multi-line comment.
{% endcomment %}

模板過濾器是在變數被顯示前修改它的值的一個簡單方法。 過濾器使用管道字元,如下所示:

{{ name|lower }}

顯示的內容是變數 {{ name }} 被過濾器 lower 處理後的結果,它功能是轉換文字為小寫
具體過濾器方法可以網上找一下資料。


include 模板標籤
內建模板標籤:該標籤允許在(模板中)包含其它的模板的內容。就是html裡面的iframe
下面這兩個例子都包含了 nav.html 模板。這兩個例子是等價的,它們證明單/雙引號都是允許的。

{% include 'nav.html' %}
{% include "nav.html" %}

下面的例子包含了 includes/nav.html 模板的內容:

{% include 'includes/nav.html' %}

下面的例子包含了以變數 template_name 的值為名稱的模板內容:

{% include template_name %}

模板繼承
本質上來說,模板繼承就是先構造一個基礎框架模板,而後在其子模板中對它所包含站點公用部分和定義塊進行過載。
就是說,比如每個網頁都包含<HTML></HTML> 等重複的程式碼
第一步是定義 基礎模板 , 該框架之後將由 子模板 所繼承。 以下是我們目前所講述範例的基礎模板

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>Thanks for visiting my site.</p>
    {% endblock %}
</body>
</html>

這個叫做 base.html 的模板定義了一個簡單的 HTML 框架文件,我們將在本站點的所有頁面中使用。 子模板的作用就是過載、新增或保留那些塊的內容。
我們使用一個以前已經見過的模板標籤: {% block %} 。 所有的 {% block %} 標籤告訴模板引擎,子模板可以過載這些部分。 每個{% block %}標籤所要做的是告訴模板引擎,該模板下的這一塊內容將有可能被子模板覆蓋。
現在我們已經有了一個基本模板,我們可以修改 current_datetime.html 模板來 使用它。

{% extends "base.html" %}

{% block title %}The current time{% endblock %}
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}

模板引擎發現了 {% extends %} 標籤, 注意到該模板是一個子模板。 模板引擎立即裝載其父模板,即本例中的 base.html 。
模板引擎注意到 base.html 中的三個 {% block %} 標籤,並用子模板的內容替換這些 block 。因此,引擎將會使用我們在 { block title %} 中定義的標題,對 {% block content %} 也是如此。 所以,網頁標題一塊將由 {% block title %}替換,同樣地,網頁的內容一塊將由 {% block content %}替換。
注意由於子模板並沒有定義 footer 塊,模板系統將使用在父模板中定義的值。 父模板 {% block %} 標籤中的內容總是被當作一條退路。


使用繼承的一種常見方式是下面的三層法:

建立 base.html 模板,在其中定義站點的主要外觀感受。 這些都是不常修改甚至從不修改的部分。

為網站的每個區域建立 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。這些模板對 base.html 進行擴充,幷包含區域特定的風格與設計。

為每種型別的頁面建立獨立的模板,例如論壇頁面或者圖片庫。 這些模板擴充相應的區域模板。

這個方法可最大限度地重用程式碼,並使得向公共區域(如區域級的導航)新增內容成為一件輕鬆的工作。


以下是使用模板繼承的一些訣竅:

如果在模板中使用 {% extends %} ,必須保證其為模板中的第一個模板標記。 否則,模板繼承將不起作用。

一般來說,基礎模板中的 {% block %} 標籤越多越好。 記住,子模板不必定義父模板中所有的程式碼塊,因此你可以用合理的預設值對一些程式碼塊進行填充,然後只對子模板所需的程式碼塊進行(重)定義。 俗話說,鉤子越多越好。

如果發覺自己在多個模板之間拷貝程式碼,你應該考慮將該程式碼段放置到父模板的某個 {% block %} 中。

如果你需要訪問父模板中的塊的內容,使用 {{ block.super }}這個標籤吧,這一個魔法變數將會表現出父模板中的內容。 如果只想在上級程式碼塊基礎上新增內容,而不是全部過載,該變數就顯得非常有用了。

不允許在同一個模板中定義多個同名的 {% block %} 。 存在這樣的限制是因為block 標籤的工作方式是雙向的。 也就是說,block 標籤不僅挖了一個要填的坑,也定義了在父模板中這個坑所填充的內容。如果模板中出現了兩個相同名稱的 {% block %} 標籤,父模板將無從得知要使用哪個塊的內容。

{% extends %} 對所傳入模板名稱使用的載入方法和 get_template() 相同。 也就是說,會將模板名稱被新增到 TEMPLATE_DIRS 設定之後。

多數情況下, {% extends %} 的引數應該是字串,但是如果直到執行時方能確定父模板名,這個引數也可以是個變數。 這使得你能夠實現一些很酷的動態功能。



在檢視中使用模板
模版是以Html形式顯示的。要在django中使用,首先要告訴模版存放在那裡。也就是模版載入。開啟你的settings.py配置檔案,配置如下:
這裡寫圖片描述
你可以任意指定想要的目錄,只要執行 Web 伺服器的使用者可以讀取該目錄的子目錄和模板檔案

使用方式:
1.render
2.render_to_response
3.get_template()
個人比較支援第1和2的方式
這裡寫圖片描述

locals() 技巧
以下等價於上圖,將now等於current_date,既模版裡面的變數名。

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())

相關文章