Django(04):Django 模板

在上一章節中咱們使用 django.http.HttpResponse() 來輸出 "Hello World!"。該方式將數據與視圖混合在一塊兒,不符合 Django 的 MVC 思想。css

本章節咱們將爲你們詳細介紹 Django 模板的應用,模板是一個文本,用於分離文檔的表現形式和內容。html

1、模板應用實例

咱們接着上一章節的項目將在 HelloWorld 目錄底下建立 templates 目錄並創建 runoob.html文件,整個目錄結構以下:前端

HelloWorld/
|-- HelloWorld
|   |-- __init__.py
|   |-- __init__.pyc
|   |-- settings.py
|   |-- settings.pyc
|   |-- urls.py
|   |-- urls.pyc
|   |-- views.py
|   |-- views.pyc
|   |-- wsgi.py
|   `-- wsgi.pyc
|-- manage.py
`-- templates
    `-- runoob.html

runoob.html 文件代碼以下:django

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

從模板中咱們知道變量使用了雙括號。bootstrap

接下來咱們須要向Django說明模板文件的路徑,修改HelloWorld/settings.py,修改 TEMPLATES 中的 DIRS 爲 [BASE_DIR+"/templates",],以下所示:後端

...TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [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)

urls.py 文件代碼:安全

from django.urls import path
 
from . import views
 
urlpatterns = [
    path('runoob/', views.runoob),
]

能夠看到,咱們這裏使用 render 來替代以前使用的 HttpResponse。render 還使用了一個字典 context 做爲參數。app

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

再次訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

這樣咱們就完成了使用模板來輸出數據,從而實現數據與視圖分離。

接下來咱們將具體介紹模板中經常使用的語法規則。

2、Django 模板標籤

一、變量

模板語法:

view:{"HTML變量名" : "views變量名"}
HTML:{{變量名}}
from django.shortcuts import render

def runoob(request):
  views_name = "菜鳥教程"
  return  render(request,"runoob.html", {"name":views_name})

templates 中的 runoob.html :

<p>{{ name }}</p>

再次訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

二、列表

templates 中的 runoob.html中,能夠用 . 索引下標取出對應的元素。

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render

def runoob(request):
    views_list = ["菜鳥教程1","菜鳥教程2","菜鳥教程3"]
    return render(request, "runoob.html", {"views_list": views_list})

HelloWorld/templates/runoob.html 文件代碼:

<p>{{ views_list }}</p>   # 取出整個列表
<p>{{ views_list.0 }}</p> # 取出列表的第一個元素

再次訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

三、字典

templates 中的 runoob.html中,能夠用 .鍵 取出對應的值。

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render

def runoob(request):
    views_dict = {"name":"菜鳥教程"}
    return render(request, "runoob.html", {"views_dict": views_dict})

HelloWorld/templates/runoob.html 文件代碼:

<p>{{ views_dict }}</p>
<p>{{ views_dict.name }}</p>

再次訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

四、過濾器

模板語法:
{{ 變量名 | 過濾器:可選參數 }}

模板過濾器能夠在變量被顯示前修改它,過濾器使用管道字符,以下所示:

{{ name|lower }}

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

過濾管道能夠被* 套接* ,既是說,一個過濾器管道的輸出又能夠做爲下一個管道的輸入:

{{ my_list|first|upper }}

以上實例將第一個元素並將其轉化爲大寫。

有些過濾器有參數。 過濾器的參數跟隨冒號以後而且老是以雙引號包含。 例如:

{{ bio|truncatewords:"30" }}

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

其餘過濾器:

  • addslashes : 添加反斜槓到任何反斜槓、單引號或者雙引號前面。
  • date : 按指定的格式字符串參數格式化 date 或者 datetime 對象,實例:
    {{ pub_date|date:"F j, Y" }}
  • length : 返回變量的長度。

(1)default

default 爲變量提供一個默認值。

若是 views 傳的變量的布爾值是 false,則使用指定的默認值。

如下值爲 false:

0  0.0  False  0j  ""  []  ()  set()  {}  None

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
    name =0
return render(request, "runoob.html", {"name": name})

HelloWorld/templates/runoob.html 文件代碼:

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

再次訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

(2)length

返回對象的長度,適用於字符串和列表。

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

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render

def runoob(request):
    name ="菜鳥教程"
    return render(request, "runoob.html", {"name": name})

HelloWorld/templates/runoob.html 文件代碼:

{{ name|length}}

再次訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

(3)filesizeformat

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

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

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render

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

HelloWorld/templates/runoob.html 文件代碼:

{{ num|filesizeformat}}

再次訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

(4)date

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

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

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
import datetime
    now  =datetime.datetime.now()
return render(request, "runoob.html", {"time": now})

HelloWorld/templates/runoob.html 文件代碼:

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

再次訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

(5)truncatechars

若是字符串包含的字符總個數多於指定的字符數量,那麼會被截斷掉後面的部分。

截斷的字符串將以 ... 結尾。

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
    views_str = "菜鳥教程"
return render(request, "runoob.html", {"views_str": views_str})

HelloWorld/templates/runoob.html 文件代碼:

{{ views_str|truncatechars:2}}

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

(6)safe

將字符串標記爲安全,不須要轉義。

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

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

Django 會自動對 views.py 傳到HTML文件中的標籤語法進行轉義,令其語義失效。加 safe 過濾器是告訴 Django 該數據是安全的,沒必要對其進行轉義,可讓該數據語義生效。

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
    views_str = "<a href='https://www.runoob.com/'>點擊跳轉</a>"
return render(request, "runoob.html", {"views_str": views_str})

HelloWorld/templates/runoob.html 文件代碼:

{{ views_str|safe }}

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

五、if/else 標籤

基本語法格式以下:

{% if condition %}
     ... display
{% endif %}

或者:

{% if condition1 %}
   ... display 1
{% elif condition2 %}
   ... display 2
{% else %}
   ... display 3
{% endif %}

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

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

{% if athlete_list and coach_list %}
     athletes 和 coaches 變量都是可用的。
{% endif %}

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
    views_num = 88
return render(request, "runoob.html", {"num": views_num})

HelloWorld/templates/runoob.html 文件代碼:

{%if num > 90 and num <= 100 %}
優秀
{% elif num > 60 and num <= 90 %}
合格
{% else %}
一邊玩去~
{% endif %}

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

六、for 標籤

{% for %} 容許咱們在一個序列上迭代。

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

每一次循環中,模板系統會渲染在 {% for %} 和 {% endfor %} 之間的全部內容。

例如,給定一個運動員列表 athlete_list 變量,咱們可使用下面的代碼來顯示這個列表:

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

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
    views_list = ["菜鳥教程","菜鳥教程1","菜鳥教程2","菜鳥教程3",]
return render(request, "runoob.html", {"views_list": views_list})

HelloWorld/templates/runoob.html 文件代碼:

{% for i in views_list %}
{{ i }}
{% endfor %}

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

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

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

HelloWorld/templates/runoob.html 文件代碼:

{% for i in views_list  reversed%}
{{ i }}
{% endfor %}

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

遍歷字典: 能夠直接用字典 .items 方法,用變量的解包分別獲取鍵和值。

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
    views_dict = {"name":"菜鳥教程","age":18}
return render(request, "runoob.html", {"views_dict": views_dict})

HelloWorld/templates/runoob.html 文件代碼:

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

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

在 {% for %} 標籤裏能夠經過 {{forloop}} 變量獲取循環序號。

  • forloop.counter: 順序獲取循環序號,從 1 開始計算
  • forloop.counter0: 順序獲取循環序號,從 0 開始計算
  • forloop.revcounter: 倒敘獲取循環序號,結尾序號爲 1
  • forloop.revcounter0: 倒敘獲取循環序號,結尾序號爲 0
  • forloop.first(通常配合if標籤使用): 第一條數據返回 True,其餘數據返回 False
  • forloop.last(通常配合if標籤使用): 最後一條數據返回 True,其餘數據返回 False

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
     views_list = ["a", "b", "c", "d", "e"]
return render(request, "runoob.html", {"listvar": views_list})

HelloWorld/templates/runoob.html 文件代碼:

{% for i in listvar %}
    {{ forloop.counter }}
    {{ forloop.counter0 }}
    {{ forloop.revcounter }}
    {{ forloop.revcounter0 }}
    {{ forloop.first }}
    {{ forloop.last }}
{% endfor %}

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

{% empty %}

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

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
  views_list = []
return render(request, "runoob.html", {"listvar": views_list})

HelloWorld/templates/runoob.html 文件代碼:

{% for i in listvar %}
    {{ forloop.counter0 }}
{% empty %}
    空空如也~
{% endfor %}

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

能夠嵌套使用 {% for %} 標籤:

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

七、ifequal/ifnotequal 標籤

{% ifequal %} 標籤比較兩個值,當他們相等時,顯示在 {% ifequal %} 和 {% endifequal %} 之中全部的值。

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

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

和 {% if %} 相似, {% ifequal %} 支持可選的 {% else%} 標籤:8

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

八、註釋標籤

Django 註釋使用 {# #}。

{# 這是一個註釋 #}

九、include 標籤

{% include %} 標籤容許在模板中包含其它的模板的內容。

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

{% include "nav.html" %}

3、csrf_token

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

若是不用{% csrf_token %}標籤,在用 form 表單時,要再次跳轉頁面會報403權限錯誤。

用了{% csrf_token %}標籤,在 form 表單提交數據時,纔會成功。

解析:

首先,向瀏覽器發送請求,獲取登陸頁面,此時中間件 csrf 會自動生成一個隱藏input標籤,該標籤裏的 value 屬性的值是一個隨機的字符串,用戶獲取到登陸頁面的同時也獲取到了這個隱藏的input標籤。

而後,等用戶須要用到form表單提交數據的時候,會攜帶這個 input 標籤一塊兒提交給中間件 csrf,緣由是 form 表單提交數據時,會包括全部的 input 標籤,中間件 csrf 接收到數據時,會判斷,這個隨機字符串是否是第一次它發給用戶的那個,若是是,則數據提交成功,若是不是,則返回403權限錯誤。

4、自定義標籤和過濾器

一、在 app 目錄下建立 templatetags 目錄(目錄名只能是 templatetags)。

二、在 templatetags 目錄下建立任意 py 文件,如:my_tags.py

三、在該 py 文件下:

from django import template

register = template.Library()   #register的名字是固定的,不可改變

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

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

@register.filter
def my_filter(v1, v2):
    return v1 * v2

五、利用裝飾器 @register.simple_tag 自定義標籤。

@register.simple_tag
def my_tag1(v1, v2, v3):
    return v1 * v2 * v3

六、在使用自定義標籤和過濾器前,要在 html 文件 body 的最上方中導入該 py 文件。

{% load my_tags %}

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

{{ 11|my_filter:22 }}

八、在 HTML 中使用自定義標籤。

{% my_tag1 11 22 33 %}

九、語義化標籤

在該 py 文件中導入 mark_safe。

from django.utils.safestring import mark_safe

定義標籤時,用上 mark_safe 方法,令標籤語義化,至關於 jQuery 中的 html() 方法。

和前端HTML文件中的過濾器 safe 效果同樣。

@register.simple_tag
def my_html(v1, v2):
    temp_html = "<input type='text' id='%s' class='%s' />" %(v1, v2)
    return mark_safe(temp_html)

在HTML中使用該自定義標籤,在頁面中動態建立標籤。

{% my_html "zzz" "xxx" %}

5、配置靜態文件

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

二、在 settings 文件的最下方配置添加如下配置:

STATIC_URL = '/static/' # 別名 
STATICFILES_DIRS = [ 
    os.path.join(BASE_DIR, "statics"), 
]

三、在 statics 目錄下建立 css 目錄,js 目錄,images 目錄,plugins 目錄, 分別放 css文件,js文件,圖片,插件。

四、把 bootstrap 框架放入插件目錄 plugins。

五、在 HTML 文件的 head 標籤中引入 bootstrap。

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

<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">

在模板中使用須要加入 {% load static %} 代碼,如下實例咱們從靜態目錄中引入圖片。

HelloWorld/HelloWorld/views.py 文件代碼:

from django.shortcuts import render
def runoob(request):
    name ="菜鳥教程"
return render(request, "runoob.html", {"name": name})

HelloWorld/templates/runoob.html 文件代碼:

{% load static %}
{{name}}<img src="{% static "images/runoob-logo.png" %}" alt="runoob-logo">

再訪問訪問 http://127.0.0.1:8000/runoob,能夠看到頁面:

6、模板繼承

模板能夠用繼承的方式來實現複用,減小冗餘內容。

網頁的頭部和尾部內容通常都是一致的,咱們就能夠經過模板繼承來實現複用。

父模板用於放置可重複利用的內容,子模板繼承父模板的內容,並放置本身的內容。

一、父模板

標籤 block...endblock: 父模板中的預留區域,該區域留給子模板填充差別性的內容,不一樣預留區域名字不能相同。

{% block 名稱 %} 
預留給子模板的區域,能夠設置設置默認內容
{% endblock 名稱 %}

二、子模板

子模板使用標籤 extends 繼承父模板:

{% extends "父模板路徑"%} 

子模板若是沒有設置父模板預留區域的內容,則使用在父模板設置的默認內容,固然也能夠都不設置,就爲空。

子模板設置父模板預留區域的內容:

{ % block 名稱 % }
內容 
{% endblock 名稱 %}

接下來咱們先建立以前項目的 templates 目錄中添加 base.html 文件,代碼以下:

HelloWorld/templates/base.html 文件代碼:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body>
    <h1>Hello World!</h1>
    <p>菜鳥教程 Django 測試。</p>
    {% block mainbody %}
       <p>original</p>
    {% endblock %}
</body>
</html>

以上代碼中,名爲 mainbody 的 block 標籤是能夠被繼承者們替換掉的部分。

全部的 {% block %} 標籤告訴模板引擎,子模板能夠重載這些部分。

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

HelloWorld/templates/runoob.html 文件代碼:

{%extends "base.html" %}
 
{% block mainbody %}
<p>繼承了 base.html 文件</p>
{% endblock %}

第一行代碼說明 runoob.html 繼承了 base.html 文件。能夠看到,這裏相同名字的 block 標籤用以替換 base.html 的相應 block。

從新訪問地址 http://127.0.0.1:8000/runoob,輸出結果以下:

相關文章
相關標籤/搜索