1. 程式人生 > 實用技巧 >04.django之模板系統

04.django之模板系統

一、語法

"""
{{ }} 和  {% %}
變數相關的用{{ }},邏輯相關的用{% %}
"""

二、句點符(.)

"""
模版系統遇到點("."),它將以這樣的順序查詢:
字典查詢(Dictionary lookup)
屬性或方法查詢(Attribute or method lookup)
數字索引查詢(Numeric index lookup)

如果使用的變數不存在, 模版系統將插入 string_if_invalid 選項的值, 
它被預設設定為'' (空字串) 。
"""

views程式碼:

def index(request):
    import datetime
    s 
= "hello" l = [111, 222, 333] # 列表 dic = {"name": "yuan", "age": 18} # 字典 date = datetime.date(1993, 5, 2) # 日期物件 class Person(object): def __init__(self, name): self.name = name def dream(self): return 'dreamer' person_aaa = Person("chao
") # 自定義類物件 person_bbb = Person("yantao") person_ccc = Person("jinxin") person_list = [person_aaa, person_bbb, person_ccc] return render(request, "index.html", {"l": l, "dic": dic, "date": date, "person_list": person_list}) # return render(request,'index.html',locals()) #locals()獲取函式內容所有的變數,然後通過render方法給了index.html檔案進行模板渲染,如果你圖省事,你可以用它,但是很多多餘的變數也被傳進去了,效率低

模板:

<h4>{{s}}</h4>
<h4>列表:{{ l.0 }}</h4>
<h4>列表:{{ l.2 }}</h4>
<h4>字典:{{ dic.name }}</h4>
<h4>日期:{{ date.year }}</h4>

<!--取列表的第1個物件的name屬性的值-->
<h4>類物件列表:{{ person_list.0.name }}</h4>
<!--取列表的第1個物件的dream方法的返回值,如果沒有返回值,拿到的是none-->
<h4>類物件列表:{{ person_list.0.dream }}</h4>
注意:
    呼叫物件裡面的方法的時候,不需要寫括號來執行,並且只能執行不需要傳引數的方法,如果你的這個方法需要傳引數,那麼模板語言不支援,不能幫你渲染

js程式碼中使用模板:

# 我們直接在js程式碼中使用模板語法的時候,模板渲染的時候會有個轉義的動作,
# 將s = ['哈哈','xx']這種資料中的元素的引號變為一個特殊符號:
    <script>
        // 不加safe的話,引號會被轉義。
        // var a = {{ s }}
        // var a = [&#39;哈哈&#39;, &#39;xx&#39;];
        // console.log(a[0])
        // 加上safe就正常了
        var a = {{ s|safe }};
        console.log(a[0])
        // 還要注意,當我們模板渲染的時候,後端返回的資料是字串的話,我們需要將{{ s }}外面加上引號
        比如s = '哈哈'
        js中的寫法
        var a = '{{ s }}'
    </script>   

三、過濾器

在Django的模板語言中,通過使用過濾器來改變變數的顯示。

注意:

  1. 過濾器支援“鏈式”操作。即一個過濾器的輸出作為另一個過濾器的輸入。
  2. 過濾器可以接受引數,例如:{{ sss|truncatewords:30 }},這將顯示sss的前30個詞。
  3. 過濾器引數包含空格的話,必須用引號包裹起來。比如使用逗號和空格去連線一個列表中的元素,如:{{ list|join:', ' }}
  4. '|'左右沒有空格沒有空格沒有空格

1、default

# 如果一個變數是false或者為空,使用給定的預設值。 否則,使用變數的值。
{{ value|default:"nothing"}}

2、length

# 返回值的長度,作用於字串和列表。
{{ value|length }}
# 返回value的長度,如 value=['a', 'b', 'c', 'd']的話,就顯示4.

3、filesizeformat

{{ value|filesizeformat }}
# 將值格式化為一個 “人類可讀的” 檔案尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如

4、slice

{{value|slice:"2:-1"}}
# 切片,如果 value="hello world",還有其他可切片的資料型別

5、date

{{ value|date:"Y-m-d H:i:s"}}
# 格式化,如果 value=datetime.datetime.now()

6、safe

  Django的模板中在進行模板渲染的時候會對HTML標籤和JS等語法標籤進行自動轉義,原因顯而易見,這樣是為了安全,django擔心這是使用者新增的資料,比如評論的時候寫了一段js程式碼,這個評論一提交,js程式碼就執行啦,如果寫個彈窗的死迴圈,就一直彈框,叫xss攻擊,所以瀏覽器不讓你這麼搞,給你轉義了。
  但是有的時候我們可能不希望這些HTML元素被轉義,比如我們做一個內容管理系統,後臺新增的文章中是經過修飾的,這些修飾可能是通過一個類似於FCKeditor編輯加註了HTML修飾符的文字,如果自動轉義的話顯示的就是保護HTML標籤的原始檔。為了在Django中關閉HTML的自動轉義有兩種方式,如果是一個單獨的變數我們可以通過過濾器“|safe”的方式告訴Django這段程式碼是安全的不必轉義。

7、truncatechars

{{ value|truncatechars:9}} #注意:最後那三個省略號也是9個字元裡面的,也就是這個9截斷出來的是6個字元+3個省略號,有人會說,怎麼展開啊,配合前端的點選事件就行啦

# 如果字串字元多於指定的字元數量,那麼會被截斷。截斷的字串將以可翻譯的省略號序列(“...”)結尾

8、truncatewords

{{ value|truncatewords:3}}  #上面例子得到的結果是 'hello girl h1...'

# 在一定數量的字後截斷字串,是截多少個單詞。
# 例如:‘hello girl hi baby yue ma’,

9、cut

{{ value|cut:' ' }}
# 移除value中所有的與給出的變數相同的字串
# 如果value為'i love you',那麼將輸出'iloveyou'.

10、join

{{ list|join:', ' }}
# 使用字串連線列表,{{ list|join:', ' }},就像Python的str.join(list)

四、標籤tags

1.for標籤

# for 迴圈每一個元素,for+TAB生成for迴圈結構,複雜一些功能需要通過js
{% for person in person_list %}
    <p>{{ person.name }}</p>  <!--凡是變數都要用兩個大括號括起來-->
{% endfor %}
# 可以利用{% for obj in list reversed %}反向完成迴圈。

遍歷一個字典:

{% for key,val in dic.items %}
    <p>{{ key }}:{{ val }}</p>
{% endfor %}
# 注:迴圈序號可以通過{{forloop}}顯示,必須在迴圈內部用
forloop.counter            當前迴圈的索引值(從1開始),forloop是迴圈器,通過點來使用功能
forloop.counter0           當前迴圈的索引值(從0開始)
forloop.revcounter         當前迴圈的倒序索引值(從1開始)
forloop.revcounter0        當前迴圈的倒序索引值(從0開始)
forloop.first              當前迴圈是不是第一次迴圈(布林值)
forloop.last               當前迴圈是不是最後一次迴圈(布林值)
forloop.parentloop         本層迴圈的外層迴圈的物件,再通過上面的幾個屬性來顯示外層迴圈的計數等

for ... empty

for 標籤帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,可以有所操作。
{% for person in person_list %}
    <p>{{ person.name }}</p>

{% empty %}
    <p>sorry,no person here</p>
{% endfor %}

2、if標籤

{% if user_list|length > 5 %}  <!--結合過濾器來使用-->
  七座豪華SUV
{% else %}
    黃包車
{% endif %}

3、with

# 使用一個簡單地名字快取一個複雜的變數,多用於給一個複雜的變數起別名
{% with total=business.employees.count %}
    {{ total }} <!--只能在with語句體內用-->
{% endwith %}

{% with business.employees.count as total %}
    {{ total }}
{% endwith %}

五、模板繼承

模板繼承可以建立一個基本的骨架模板,包含站點的全部元素,並且可以定義能被子模板覆蓋的blocks。

index2.html 母版

{#做一個首頁一樣的頁面#}
<div class="outer">
    <div class="nav">標題</div>

    <div class="left">
        <div class="student manage"><a href="/student">學生管理</a></div>
        <div class="teacher manage"><a href="">老師管理</a></div>
        <div class="course manage"><a href="">課程管理</a></div>
        <div class="classes manage"><a href="">班級管理</a></div>
    </div>

    <div class="content">

        {% block content %}
            <h1 class="hh">WELCOME TO LOGIN</h1>
        {% endblock %}
{#        <h1 class="hh">WELCOME TO LOGIN</h1>#}
    </div>
</div>

繼承母版

{#繼承 母版 母版就是index2.html#}
{% extends "index2.html" %}
{% load staticfiles %}

{% block content %}
    {#        這裡把繼承過來的class=content重寫了,但是還想用父類裡的<h1>#}
    {{ block.super }}

    {% for student in student_list %}
            <h2>學生{{ student }}</h2>
    {% endfor %}
    {% include "include_在模板中新增模板.html" %}
{% endblock %}


{#1.如果在模板中使用 {% extends %} ,必須保證其為模板中的第一個模板標記。否則,模板繼承將不起作用。#}
{#2.一般來說,基礎模板中的{% block %} 標籤越多越好。記住,子模板不必定義模板中所有的程式碼塊,因此你可以#}
{#用合理的預設值對一些程式碼塊進行填充,然後只對子模板所需的程式碼進行(重)定義。俗話說,鉤子越多越好#}
{#3.如果發覺自己在多個模板之間拷貝程式碼,你應該考慮將該程式碼段放置到父模板的某個{% block %} 中。#}
{#    如果你需要訪問父模板中的塊的內容,使用{{ block.super }}這個標籤吧。這一個魔法變數將會表現出#}
{#    父模板中的內容。如果只想在上級程式碼基礎上新增內容,而不是全部過載,該變數就顯得非常有用了。#}
{#4.不允許在同一個模板中定義多個同名的{% block %} 。 存在這樣的限制是因為block 標籤的工作方式是雙向的。#}
{#    也就是說,block 標籤不僅挖了一個要填的坑,也定義了在父模板中這個坑所填充的內容。如果模板中出現#}
{#    了兩個相同名稱 {% block %} 標籤,父模板將無從得知要使用哪個塊的內容。#}

六、元件

可以將常用的頁面內容如導航條,頁尾資訊等元件儲存在單獨的檔案中,然後在需要使用的地方,檔案的任意位置按如下語法匯入即可。

{% include 'navbar.html' %}

例:

有如下導航欄:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .c1{
            background-color: red;
            height: 40px;
        }
    </style>
</head>
<body>

<div class="c1">
    <div>
        <a href="">xx</a>
        <a href="">dd</a>
    </div>
</div>

</body>
</html>

嵌入到 test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% include 'nav.html' %}
<h1>xxxxxxxxxx</h1>
</body>
</html>

元件和外掛的區別:

"""
元件是提供某一完整功能的模組,如:編輯器元件,QQ空間提供的關注元件 等
而外掛更傾向封閉某一功能方法的函式。
這兩者的區別在 Javascript 裡區別很小,元件這個名詞用得不多,一般統稱外掛。
"""

七、靜態檔案相關

前端頁面引入靜態檔案的寫法,因為別名也可能會修改,所以使用路徑的時候通過load static來找到別名,通過別名對映路徑的方式來獲取靜態檔案

某個檔案多處被用到可以存為一個變數

{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>

form表單等路徑問題:

<form action="/login/"></form>
<img src="/static/1.jpg" alt="">
等標籤需要寫路徑的地方,如果寫的是相對路徑,那麼前置的/這個斜槓必須寫上,
不然這個請求會拼接當前網頁的路徑來發送請求,就不能匹配我們的後端路徑了