天天看點

Django 模闆

在上一章節中我們使用 django.http.HttpResponse() 來輸出 "Hello World!"。該方式将資料與視圖混合在一起,不符合 Django 的 MVC 思想。

本章節我們将為大家詳細介紹 Django 模闆的應用,模闆是一個文本,用于分離文檔的表現形式和内容。

我們接着上一章節的項目将在 HelloWorld 目錄底下建立 templates 目錄并建立 runoob.html檔案,整個目錄結構如下:

runoob.html 檔案代碼如下:

<h1>{{ hello }}</h1>

從模闆中我們知道變量使用了雙括号。

接下來我們需要向Django說明模闆檔案的路徑,修改HelloWorld/settings.py,修改 TEMPLATES 中的 DIRS 為 <b>[os.path.join(BASE_DIR, 'templates')]</b>,如下所示:

...

TEMPLATES = [

    {

        'BACKEND': 'django.template.backends.django.DjangoTemplates',

        'DIRS': [os.path.join(BASE_DIR, 'templates')],       # 修改位置

        'APP_DIRS': True,

        'OPTIONS': {

            'context_processors': [

                'django.template.context_processors.debug',

                'django.template.context_processors.request',

                'django.contrib.auth.context_processors.auth',

                'django.contrib.messages.context_processors.messages',

            ],

        },

    },

]

我們現在修改 views.py,增加一個新的對象,用于向模闆送出資料:

from django.shortcuts import render

def runoob(request):

context = {}

context['hello'] = 'Hello World!'

return render(request, 'runoob.html', context)

from django.urls import path

from . import views

urlpatterns = [

path('runoob/', views.runoob),

可以看到,我們這裡使用 render 來替代之前使用的 HttpResponse。render 還使用了一個字典 context 作為參數。

context 字典中元素的鍵值 hello 對應了模闆中的變量 {{ hello }}。

再次通路 http://127.0.0.1:8000/runoob,可以看到頁面:

Django 模闆

這樣我們就完成了使用模闆來輸出資料,進而實作資料與視圖分離。

接下來我們将具體介紹模闆中常用的文法規則。

模闆文法:

  views_name = "菜鳥教程"

  return  render(request,"runoob.html", {"name":views_name})

templates 中的 runoob.html :

Django 模闆
Django 模闆

templates 中的 runoob.html中,可以用 . 索引下标取出對應的元素。

    views_list = ["菜鳥教程1","菜鳥教程2","菜鳥教程3"]

    return render(request, "runoob.html", {"views_list": views_list})

&lt;p&gt;{{ views_list }}&lt;/p&gt; # 取出整個清單

&lt;p&gt;{{ views_list.0 }}&lt;/p&gt; # 取出清單的第一個元素

Django 模闆

templates 中的 runoob.html中,可以用 .鍵 取出對應的值。

    views_dict = {"name":"菜鳥教程"}

    return render(request, "runoob.html", {"views_dict": views_dict})

&lt;p&gt;{{ views_dict }}&lt;/p&gt;

&lt;p&gt;{{ views_dict.name }}&lt;/p&gt;

Django 模闆

模闆過濾器可以在變量被顯示前修改它,過濾器使用管道字元,如下所示:

{{ name }} 變量被過濾器 lower 處理後,文檔大寫轉換文本為小寫。

過濾管道可以被* 套接* ,既是說,一個過濾器管道的輸出又可以作為下一個管道的輸入:

以上執行個體将第一個元素并将其轉化為大寫。

有些過濾器有參數。 過濾器的參數跟随冒号之後并且總是以雙引号包含。 例如:

這個将顯示變量 bio 的前30個詞。

其他過濾器:

addslashes : 添加反斜杠到任何反斜杠、單引号或者雙引号前面。

date : 按指定的格式字元串參數格式化 date 或者 datetime 對象,執行個體:

length : 傳回變量的長度。

default

default 為變量提供一個預設值。

如果 views 傳的變量的布爾值是 false,則使用指定的預設值。

以下值為 false:

    name =0

    return render(request, "runoob.html", {"name": name})

{{ name|default:"菜鳥教程666" }}

Django 模闆

length

傳回對象的長度,适用于字元串和清單。

字典傳回的是鍵值對的數量,集合傳回的是去重後的長度。

    name ="菜鳥教程"

{{ name|length}}

Django 模闆

filesizeformat

以更易讀的方式顯示檔案的大小(即'13 KB', '4.1 MB', '102 bytes'等)。

    num=1024

    return render(request, "runoob.html", {"num": num})

{{ num|filesizeformat}}

Django 模闆

date

根據給定格式對一個日期變量進行格式化。

格式 Y-m-d H:i:s傳回 年-月-日 小時:分鐘:秒 的格式時間。

    import datetime

    now  =datetime.datetime.now()

    return render(request, "runoob.html", {"time": now})

{{ time|date:"Y-m-d" }}

Django 模闆

truncatechars

如果字元串包含的字元總個數多于指定的字元數量,那麼會被截斷掉後面的部分。

截斷的字元串将以 ... 結尾。

    views_str = "菜鳥教程"

    return render(request, "runoob.html", {"views_str": views_str})

{{ views_str|truncatechars:2}}

再通路通路 http://127.0.0.1:8000/runoob,可以看到頁面:

Django 模闆

safe

将字元串标記為安全,不需要轉義。

要保證 views.py 傳過來的資料絕對安全,才能用 safe。

和後端 views.py 的 mark_safe 效果相同。

Django 會自動對 views.py 傳到HTML檔案中的标簽文法進行轉義,令其語義失效。加 safe 過濾器是告訴 Django 該資料是安全的,不必對其進行轉義,可以讓該資料語義生效。

    views_str = "&lt;a href='https://www.runoob.com/'&gt;點選跳轉&lt;/a&gt;"

{{ views_str|safe }}

Django 模闆

基本文法格式如下:

或者:

根據條件判斷是否輸出。if/else 支援嵌套。

{% if %} 标簽接受 and , or 或者 not 關鍵字來對多個變量做判斷 ,或者對變量取反( not ),例如:

    views_num = 88

    return render(request, "runoob.html", {"num": views_num})

{%if num &gt; 90 and num &lt;= 100 %}

優秀

{% elif num &gt; 60 and num &lt;= 90 %}

合格

{% else %}

一邊玩去~

{% endif %}

Django 模闆

{% for %} 允許我們在一個序列上疊代。

與 Python 的 for 語句的情形類似,循環文法是 for X in Y ,Y 是要疊代的序列而 X 是在每一個特定的循環中使用的變量名稱。

每一次循環中,模闆系統會渲染在 {% for %} 和 {% endfor %} 之間的所有内容。

例如,給定一個運動員清單 athlete_list 變量,我們可以使用下面的代碼來顯示這個清單:

    views_list = ["菜鳥教程","菜鳥教程1","菜鳥教程2","菜鳥教程3",]

{% for i in views_list %}

{{ i }}

{% endfor %}

Django 模闆

給标簽增加一個 reversed 使得該清單被反向疊代:

{% for i in views_list reversed%}

Django 模闆

周遊字典: 可以直接用字典 .items 方法,用變量的解包分别擷取鍵和值。

    views_dict = {"name":"菜鳥教程","age":18}

{% for i,j in views_dict.items %}

{{ i }}---{{ j }}

Django 模闆

在 {% for %} 标簽裡可以通過 {{forloop}} 變量擷取循環序号。

forloop.counter: 順序擷取循環序号,從 1 開始計算

forloop.counter0: 順序擷取循環序号,從 0 開始計算

forloop.revcounter: 倒叙擷取循環序号,結尾序号為 1

forloop.revcounter0: 倒叙擷取循環序号,結尾序号為 0

forloop.first(一般配合if标簽使用): 第一條資料傳回 True,其他資料傳回 False

forloop.last(一般配合if标簽使用): 最後一條資料傳回 True,其他資料傳回 False

     views_list = ["a", "b", "c", "d", "e"]

     return render(request, "runoob.html", {"listvar": views_list})

{% for i in listvar %}

{{ forloop.counter }}

{{ forloop.counter0 }}

{{ forloop.revcounter }}

{{ forloop.revcounter0 }}

{{ forloop.first }}

{{ forloop.last }}

Django 模闆

{% empty %}

可選的 {% empty %} 從句:在循環為空的時候執行(即 in 後面的參數布爾值為 False )。

  views_list = []

  return render(request, "runoob.html", {"listvar": views_list})

空空如也~

Django 模闆

可以嵌套使用 {% for %} 标簽:

{% ifequal %} 标簽比較兩個值,當他們相等時,顯示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。

下面的例子比較兩個模闆變量 user 和 currentuser :

和 {% if %} 類似, {% ifequal %} 支援可選的 {% else%} 标簽:8

Django 注釋使用 {# #}。

{% include %} 标簽允許在模闆中包含其它的模闆的内容。

下面這個例子都包含了 nav.html 模闆:

csrf_token 用于form表單中,作用是跨站請求僞造保護。

如果不用{% csrf_token %}标簽,在用 form 表單時,要再次跳轉頁面會報403權限錯誤。

用了{% csrf_token %}标簽,在 form 表單送出資料時,才會成功。

解析:

首先,向伺服器發送請求,擷取登入頁面,此時中間件 csrf 會自動生成一個隐藏input标簽,該标簽裡的 value 屬性的值是一個随機的字元串,使用者擷取到登入頁面的同時也擷取到了這個隐藏的input标簽。

然後,等使用者需要用到form表單送出資料的時候,會攜帶這個 input 标簽一起送出給中間件 csrf,原因是 form 表單送出資料時,會包括所有的 input 标簽,中間件 csrf 接收到資料時,會判斷,這個随機字元串是不是第一次它發給使用者的那個,如果是,則資料送出成功,如果不是,則傳回403權限錯誤。

1、在應用目錄下建立 templatetags 目錄(與 templates 目錄同級,目錄名隻能是 templatetags)。

2、在 templatetags 目錄下建立任意 py 檔案,如:my_tags.py。

3、my_tags.py 檔案代碼如下:

修改 settings.py 檔案的 TEMPLATES 選項配置,添加 libraries 配置:

        'DIRS': [BASE_DIR, "/templates",],

            "libraries":{                          # 添加這邊三行配置

                'my_tags':'templatetags.my_tags'   # 添加這邊三行配置        

            }                                      # 添加這邊三行配置

4、利用裝飾器 @register.filter 自定義過濾器。

注意:裝飾器的參數最多隻能有 2 個。

5、利用裝飾器 @register.simple_tag 自定義标簽。

6、在使用自定義标簽和過濾器前,要在 html 檔案 body 的最上方中導入該 py 檔案。

7、在 HTML 中使用自定義過濾器。

8、在 HTML 中使用自定義标簽。

9、語義化标簽

在該 py 檔案中導入 mark_safe。

定義标簽時,用上 mark_safe 方法,令标簽語義化,相當于 jQuery 中的 html() 方法。

和前端HTML檔案中的過濾器 safe 效果一樣。

在HTML中使用該自定義标簽,在頁面中動态建立标簽。

1、在項目根目錄下建立 statics 目錄。

Django 模闆

2、在 settings 檔案的最下方配置添加以下配置:

Django 模闆

3、在 statics 目錄下建立 css 目錄,js 目錄,images 目錄,plugins 目錄, 分别放 css檔案,js檔案,圖檔,插件。

4、把 bootstrap 架構放入插件目錄 plugins。

5、在 HTML 檔案的 head 标簽中引入 bootstrap。

注意:此時引用路徑中的要用配置檔案中的别名 static,而不是目錄 statics。

在模闆中使用需要加入 {% load static %} 代碼,以下執行個體我們從靜态目錄中引入圖檔。

{% load static %}

{{name}}&lt;img src="{% static "images/runoob-logo.png" %}" alt="runoob-logo"&gt;

Django 模闆

模闆可以用繼承的方式來實作複用,減少備援内容。

網頁的頭部和尾部内容一般都是一緻的,我們就可以通過模闆繼承來實作複用。

父模闆用于放置可重複利用的内容,子模闆繼承父模闆的内容,并放置自己的内容。

标簽 block...endblock: 父模闆中的預留區域,該區域留給子模闆填充差異性的内容,不同預留區域名字不能相同。

子模闆使用标簽 extends 繼承父模闆:

子模闆如果沒有設定父模闆預留區域的内容,則使用在父模闆設定的預設内容,當然也可以都不設定,就為空。

子模闆設定父模闆預留區域的内容:

接下來我們先建立之前項目的 templates 目錄中添加 base.html 檔案,代碼如下:

&lt;!DOCTYPE html&gt;

&lt;html&gt;

&lt;head&gt;

&lt;meta charset="utf-8"&gt;

&lt;title&gt;菜鳥教程(runoob.com)&lt;/title&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;h1&gt;Hello World!&lt;/h1&gt;

&lt;p&gt;菜鳥教程 Django 測試。&lt;/p&gt;

{% block mainbody %}

&lt;p&gt;original&lt;/p&gt;

{% endblock %}

&lt;/body&gt;

&lt;/html&gt;

以上代碼中,名為 mainbody 的 block 标簽是可以被繼承者們替換掉的部分。

所有的 {% block %} 标簽告訴模闆引擎,子模闆可以重載這些部分。

runoob.html 中繼承 base.html,并替換特定 block,runoob.html 修改後的代碼如下:

{%extends "base.html" %}

&lt;p&gt;繼承了 base.html 檔案&lt;/p&gt;

第一行代碼說明 runoob.html 繼承了 base.html 檔案。可以看到,這裡相同名字的 block 标簽用以替換 base.html 的相應 block。

重新通路位址 http://127.0.0.1:8000/runoob,輸出結果如下:

Django 模闆