Django之模板系統

一.語法

模板渲染的官方文檔

關於模板渲染你只需要記兩種特殊符號(語法):

{{ }}和 {% %}

變量相關的用{{}},邏輯相關的用{%%}。

二.變量

  • 在Django的模板語言中按此語法使用:{{ 變量名 }}。
  • 當模版引擎遇到一個變量,它將計算這個變量,然後用結果替換掉它本身。 變量的命名包括任何字母數字以及下劃線 ("_")的組合。
    變量名稱中不能有空格或標點符號。
  • 深度查詢據點符(.)在模板語言中有特殊的含義。當模版系統遇到點("."),它將以這樣的順序查詢:
        字典查詢(Dictionary lookup)
        屬性或方法查詢(Attribute or method lookup)
        數字索引查詢(Numeric index lookup)

示例:

views.py:

def index1(request):
    num = 10
    name = '張三'
    name_list = ['李四','王五']
    dic = {'name':'test','age':23,'hoby':'girl'}

    class Person:
        def __init__(self):
            self.name = 'dog'
        def dream(self):
            return 'dreamer'

    a = Person()  #返回一個對象

    return render(request,'index1.html',{'num':num,'name':name,'name_list':name_list,'dic':dic,'a':a})
    # return render(request,'index.html',locals())
    #locals()獲取函數內容所有的變量,然後通過render方法給了index.html文件進行模板渲染,如果你圖省事,你可以用它,但是很多多餘的變量也被傳進去了,效率低

index1.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>模板</h1>
<p>{{ num }}</p>
<p>{{ name }}</p>
<p>{{ name_list }}</p>
<p>{{ name_list.0 }}</p>
<p>{{ dic }}</p>
<p>{{ dic.age }}</p>
<p>{{ a.name }}</p>
</body>
</html>

三.過濾器

在Django的模板語言中,通過使用 過濾器 來改變變量的顯示。
過濾器的語法: {{ value|filter_name:參數 }}
使用管道符"|"來應用過濾器。
例如:{{ name|lower }}會將name變量應用lower過濾器之後再顯示它的值。lower在這裏的作用是將文本全都變成小寫。
注意事項:

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

Django的模板語言中提供了大約六十個內置過濾器。

length

返回值的長度,作用於字符串和列表。

{{ name_list|length }}

default

如果一個變量是false或者爲空,使用給定的默認值。 否則,使用變量的值。

{{ xx|default:'啥也沒有' }} #沒有xx這個值就顯示【啥也沒有】

filesizeformat

將值格式化爲一個 “人類可讀的” 文件尺寸 (例如 ‘13 KB’, ‘4.1 MB’, ‘102 bytes’, 等等)。例如:

movesizi = 123342224
{{ movesizi|filesizeformat }}  #結果:117.6 MB

slice

切片,如果 value=“hello world”,還有其他可切片的數據類型

name = 'zhangsan'
{{ name|slice:'0:3' }}  #zha

date

格式化,如果 value=datetime.datetime.now()

格式化,如果 value=datetime.datetime.now()
{{ now|date:'Y-m-d' }}  #2020-03-12  不加date:March 12, 2020, 2:19 p.m.

truncatechars

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

words = 'i love you my girl'
{{ words|truncatechars:'9' }}   #結果:i love...  點也算在內

truncatewords

在一定數量的字後截斷字符串,是截多少個單詞。

例如:‘hello girl hi baby yue ma’,
{{ words1|truncatewords:'3' }}    #結果:hello girl hi ...

cut

移除value中所有的與給出的變量相同的字符串

words1 = 'hello girl hi baby yue ma'
{{ words1|cut:' ' }}  #移除空格  結果:hellogirlhibabyyuema

join

使用字符串連接列表,{{ list|join:’, ’ }},就像Python的str.join(list)

name_list = ['李四','王五']
{{ name_list|join:'*' }}  #以星號連接  結果:李四*王五

safe
Django的模板中在進行模板渲染的時候會對HTML標籤和JS等語法標籤進行自動轉義,原因顯而易見,這樣是爲了安全,django擔心這是用戶添加的數據,比如如果有人給你評論的時候寫了一段js代碼,這個評論一提交,js代碼就執行啦,這樣你是不是可以搞一些壞事兒了,這叫做xss攻擊,所以瀏覽器不讓你這麼搞,給你轉義了。但是有的時候我們可能不希望這些HTML元素被轉義,如果是一個單獨的變量我們可以通過過濾器“|safe”的方式告訴Django這段代碼是安全的不必轉義。
我們去network那個地方看看,瀏覽器看到的都是渲染之後的結果,通過network的response的那個部分可以看到,這個a標籤全部是特殊符號包裹起來的,並不是一個標籤,這都是django搞得事情。
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200312143837278.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MjUzMzcw,size_16,color_FFFFFF,t_70
使用safe之後,允許HTML元素被轉義,這個時候就是一個正常的a標籤了:
在這裏插入圖片描述

四.標籤Tags

標籤看起來像是這樣的: {% tag %}。標籤比變量更加複雜:一些在輸出中創建文本,一些通過循環或邏輯來控制流程,一些加載其後的變量將使用到的額外信息到模版中。一些標籤需要開始和結束標籤 (例如{% tag %} …標籤 內容 … {% endtag %})。

for標籤
遍歷每一個元素: 寫個for,然後 tab鍵自動生成for循環的結構,循環很基礎,就這麼簡單的用,沒有什麼break之類的,複雜一些的功能,你要通過js

列表:
<ul>
    {% for name in name_list %}
        <li>{{ name }}</li>
    {% endfor %}
</ul>
字典:
<ol>
    {% for key,value in dic.items %} #和Python裏面一樣 這裏可以循環key,values
        <li>{{ key }}-----{{ value }}</li>
    {% endfor %}
</ol>

循環序號:

注:循環序號可以通過{{forloop}}顯示,必須在循環內部用  
forloop.counter            當前循環的索引值(1開始),forloop是循環器,通過點來使用功能
forloop.counter0           當前循環的索引值(從0開始)
forloop.revcounter         當前循環的倒序索引值(從1開始)
forloop.revcounter0        當前循環的倒序索引值(從0開始)
forloop.first              當前循環是不是第一次循環(布爾值)
forloop.last               當前循環是不是最後一次循環(布爾值)
forloop.parentloop         本層循環的外層循環的對象,再通過上面的幾個屬性來顯示外層循環的計數等

forloop.parentloop示例:

d2 = [[11,22],[33,44]]
<ol>
    {% for dd2 in d2 %}
        <li>
            {% for ddd2 in dd2 %}
                {{ forloop.parentloop.counter }}
                {{ forloop.counter}}  
                <a href="">{{ ddd2 }}</a>
            {% endfor %}
        </li>
    {% endfor %}
</ol>
結果:
	1 1 11 1 2 22  
	2 1 33 2 2 44
解釋:
	父層循環裏面有兩個元素,第一次循環計數是1,內部循環裏面兩個值,第一次打印11 第二次打印22 計數分別爲12
	父層循環裏面有兩個元素,第一次循環計數是2,內部循環裏面兩個值,第一次打印33 第二次打印44 計數分別爲12

for … empty
for 標籤帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,可以有所操作。

<ul>
    {% for foo in d3 %}
        <li>{{ foo }}</li>
    {% empty %}
        <li>什麼也沒有</li>
    {% endfor %}
</ul>

if 標籤
{% if %}會對一個變量求值,如果它的值是“True”(存在、不爲空、且不是boolean類型的false值),對應的內容塊會輸出。

if語句支持 andor==><!=<=>=innot inisis not判斷,注意條件兩邊都有空格。

{% if num > 100 %}
    <a href="">大於100</a>
    {% elif num < 100 %}
    <a href="">小於100</a>
{% endif %}

還可以加過濾器:
{% if name_list|length > 3%}
    <a href="">大於3</a>
    {% elif name_list|length < 3%}
    <a href="">小於3</a>
    {% else %}
    <a href="">等於3</a>
{% endif %}

with
使用一個簡單地名字緩存一個複雜的變量,多用於給一個複雜的變量起別名,當你需要使用一個“昂貴的”方法(比如訪問數據庫)很多次的時候是非常有用的注意等號左右不要加空格。

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

第一種寫法:
{% with shitai=dic.name %}
    <h2>{{ shitai }}</h2>
{% endwith %}

第二種寫法(as:類似與起別名){% with dic.name as shitai %}
    <h2>{{ shitai }}</h2>
{% endwith %}

以上標籤注意事項:

1. Django的模板語言不支持連續判斷,即不支持以下寫法:
{% if a > b > c %}
...
{% endif %}

2. Django的模板語言中屬性的優先級大於方法(瞭解)
def xx(request):
d = {"a": 1, "b": 2, "c": 3, "items": "100"}
return render(request, "xx.html", {"data": d})
如上,我們在使用render方法渲染一個頁面的時候,傳的字典d有一個key是items並且還有默認的 d.items() 方法,此時在模板語言中:
{{ data.items }}
默認會取d的items key的值。並不是itemsl方法。

csrf_token

我們以post方式提交表單的時候,會報錯,還記得我們在settings裏面的中間件配置裏面把一個csrf的防禦機制給註銷了啊,本身不應該註銷的,而是應該學會怎麼使用它,並且不讓自己的操作被forbiden,通過這個東西就能搞定。
這個標籤用於跨站請求僞造保護,
在這裏插入圖片描述

五.模板繼承

Django模版引擎中最強大也是最複雜的部分就是模版繼承了。模版繼承可以讓您創建一個基本的“骨架”模版,它包含您站點中的全部元素,並且可以定義能夠被子模版覆蓋的 blocks 。
示例:

母版頁面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .nav{
            background-color: red;
            height: 40px;
        }
        .left_menu{
            background-color: green;
            color: white;
            width: 20%;
            height: 400px;
            float: left;
        }
        .content{
            width: 80%;
            float: right;
        }
        .clearfix{
            content: '';
            display: block;
            clear: both;
        }

    </style>
</head>
<body>

<div class="nav">
    <a href="">22</a>
    <a href="">23</a>
    <a href="">24</a>
    <input type="text"><button>搜索</button>
</div>

<div class="clearfix">
    <div class="left_menu">
    <ul>
        <li><a href="{% url 'app02:menu1' %}">菜單1</a></li>
        <li><a href="{% url 'app02:menu2' %}">菜單2</a></li>
        <li><a href="{% url 'app02:menu3' %}">菜單3</a></li>
    </ul>
</div>

<div class="content">
    {% block content %}
        母版頁面
    {% endblock %}
</div>
</div>

</body>
</html>
{% extends 'object.html' %}    #繼承母版頁面
{% block content %}            #預留的鉤子 用來修改內容
    {{ block.super }}          #顯示父類的內容
    首頁
{% endblock %}
{% extends 'object.html' %}
{% block content %}
    菜單3
{% endblock %}
{% extends 'object.html' %}
{% block content %}
    菜單2
{% endblock %}
{% extends 'object.html' %}
{% block content %}
    菜單1
{% endblock %}

這裏是使用繼承的一些提示:

  • 如果你在模版中使用 {% extends %}標籤,它必須是模版中的第一個標籤。其他的任何情況下,模版繼承都將無法工作,模板渲染的時候django都不知道你在幹啥。
  • 在base模版中設置越多的 {% block %}標籤越好。請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數blocks中填充合理的默認內容,然後,只定義你需要的那一個。多一點鉤子總比少一點好。
  • 如果你發現你自己在大量的模版中複製內容,那可能意味着你應該把內容移動到父模版中的一個 {% block %} 中。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章