Django 模板

Django 模板

image

模板傳值取值

後端傳值

  • 鍵值對形式:{『name』:value}
    • 精準傳值,用啥傳啥
  • 函數:locals()
    • locals()將當前名稱空間中所有的變數名全部傳遞給頁面

HTML取值

  • 變數相關:{{變數名}}
  • 邏輯相關:{% 表達式 %}

在取值的時候需要注意以下幾點

* 傳遞函數名會自動加括弧調用,並返回return後的值
* 傳遞類名會自動加括弧調用實例化成對象
* 傳遞實例化對象名也返回對象,傳遞 對象.方法 可以獲取該的返回值
* 傳遞類和函數不需要加括弧,自動加括弧調用,模板語法不支援額外的傳參(形參,實參)
* HTML頁面取值可以通過點`.`的方式取值,不論是索引還是鍵值等···
eg:<p>{{ d.hobby.3.username }}</p>
# 索引就是.下標,字典就是.鍵
<p>{{ my_int }}</p>
<p>{{ my_float }}</p>
<p>{{ my_list }}</p>
<p>{{ my_tuple }}</p>
<p>{{ my_dict }}</p>
<p>{{ my_set }}</p>
<p>{{ my_bool }}</p>
<p>{{ get_func }}</p>
<p>{{ MyClass }}</p>
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_self }}</p>
<p>{{ obj.get_static }}</p>
def func(request):
    my_int = 123
    my_float = 3.14
    my_list = [1, 2, 3, 4]
    my_tuple = (1, 2, 3, 4,)
    my_dict = {'name': 'Hammer'}
    my_set = {1, 2, 3, 4}
    my_bool = True
    def get_func():
        print('from get_func')
        return 'get_func'
    class MyClass(object):
        def get_self(self):
            return '綁定給對象的方法'
        @classmethod
        def get_cls(cls):
            return '綁定給類的方法'
        @staticmethod
        def get_static():
            return '靜態方法'
    obj = MyClass()
    return render(request,'func.html',locals())

image


過濾器

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

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

{{ name|lower }}
# 過濾器處理後轉小寫

管道符的作用:一個過濾器管道的輸出又可以作為下一個管道的輸入

default

在html文件中,default 為變數提供一個默認值,如果views傳的變數布爾值為false,則使用指定的默認值,如果為true,就使用views傳的變數值;

from django.shortcuts import render

def func(request):
    id = 0
    return render(request,'func.html',locals()) # {'id':id}

'''html'''
<p>{{ id|default:'views傳的變數布爾值為false用我吧!' }}</p>

image

length

  • 返回對象的長度,適用於字元串和列表
  • 字典返回的是鍵值對的數量,集合返回的是去重後的長度
字元串:{{ my_str|length }}
列表:{{ my_list|length }}
字典:{{ my_dict|length }}
集合:{{ my_set|length }}
def func(request):
    my_str = 'HammerZe'
    my_list = [1, 2, 3, 4]
    my_dict = {'name': 'HammerZe', 'age': 18}
    my_set = {1, 1, 2, 2, 3, 3, 4, 4}
    return render(request, 'func.html', locals())

image

filesizeformat

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

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

def func(request):
    file_data = 1024*1024
    return render(request, 'func.html', locals())
文件大小:{{ file_data|filesizeformat }}

image

date

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

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

def func(request):
    import datetime
    ctime = datetime.datetime.now()
    return render(request, 'func.html', locals())
時間:{{ ctime|date:'Y-m-d H:i:s' }}

image

truncatechars

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

截斷的字元串將以 ... 結尾,...也算三個字元,比如部落格園首頁示例

def func(request):
    trun_str = 'HammerZe真帥'
    return render(request, 'func.html', locals())
字元串截取:{{ trun_str|truncatechars:9 }}

image

truncatewords

該過濾器和truncatechars類似,但是...不計入長度,空格為分隔符,一個單詞為一個單元字元

from django.shortcuts import render
def func(request):
    trun_str = 'HammerZe Hans He'
    return render(request, 'func.html', locals())
字元串截取:{{ trun_str|truncatewords:2 }}

image

safe

將字元串標記為安全,不需要轉義。

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

後端: 使用views.py 的 mark_safe 效果相同

Django 會自動對 views.py 傳到HTML文件中的標籤語法進行轉義,令其語義失效。加 safe 過濾器是告訴 Django 該數據是安全的,不必對其進行轉義,可以讓該數據語義生效(這裡涉及到xss攻擊自行查閱)

from django.shortcuts import render
def func(request):
    unsafe_str = '<h1>不轉義,語義失效,攜帶標籤</h1>'
    safe_str = '<h1>轉義,語義生效,我是一級標題</h1>'
    # 後端取消轉義
    from django.utils.safestring import mark_safe
    safe_str1 = mark_safe('<h1>後端取消轉義</h1>')
    
    return render(request, 'func.html', locals())
{{ unsafe_str }}
{{ safe_str|safe }}
{{ safe_str1 }}

image

add

整型做加法運算,字元串做拼接

from django.shortcuts import render
def func(request):
    add_num = 100
    join_str = 'Hammer'
    return render(request, 'func.html', locals())
<p>加法運算:{{ add_num|add:100 }}</p>
<p>字元串拼接:{{ join_str|add:'Ze' }}</p>

image

標籤

注釋標籤

Django 注釋使用 {# #}

{# 這是一個注釋 #}

if/else 標籤

  • 語法格式:
{% if condition %}
     ... display
{% endif %}

或者

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

# 示例
{% if my_str %}
{{ my_str }}
{% endif %}
def func(request):
    my_str = 'HammerZe'
    return render(request, 'func.html', locals())
# 頁面返回:HammerZe

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

{% if a and b %}
     a 和 b 變數都是可用的。
{% endif %}

for 標籤

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

模板語法for循環和python 的for循環類似,支援in

from django.shortcuts import render
def func(request):
    l = [1,2,3,4]
    return render(request, 'func.html', locals())

{% for foo in l %}
{{ foo }}
{% endfor %}

image

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

{% for foo in l reversed  %}
{{ foo }}
{% endfor %}

image

遍歷字典: 可以直接用字典 .items 方法,用變數的解包分別獲取鍵和值

from django.shortcuts import render
def func(request):
    my_dict = {'name': 'HammerZe', 'age': 18, 'gender': 'male'}
    return render(request, 'func.html', locals())
# 分別獲取k,v
{% for k in my_dict  %}
{{ k }}
{#{{ v }}#}
{% endfor %}

image

# 獲取k,v
{% for k,v in my_dict.items  %}
{{ k }}
{{ v }}
{% endfor %}

image

forloop內置對象

{% for k in my_dict  %}
{{ forloop }}
{% endfor %}

image

在 {% for %} 標籤里可以通過 {{forloop}} 變數獲取循環序號。

  • forloop.counter: 順序獲取循環序號,從 1 開始計算
  • forloop.counter0: 順序獲取循環序號,從 0 開始計算
  • forloop.revcounter: 倒序獲取循環序號,結尾序號為 1
  • forloop.revcounter0: 倒序獲取循環序號,結尾序號為 0
  • forloop.first(一般配合if標籤使用): 第一條數據返回 True,其他數據返回 False
  • forloop.last(一般配合if標籤使用): 最後一條數據返回 True,其他數據返回 False
{% for i in views_list  %}
{#<p>{{ forloop.counter }}</p>#} # 1 2 3 4 5
{#<p>{{ forloop.counter0 }}</p>#} # 0 1 2 3 4
{#<p>{{ forloop.revcounter }}</p>#} # 5 4 3 2 1 
{#<p>{{ forloop.revcounter0 }}</p>#} # 4 3 2 1 0
<p>{{ forloop.first }}</p> # True False False False False 
<p>{{ forloop.last }}</p>  # False False False False True
{% endfor %}

from django.shortcuts import render
def func(request):
    views_list = ["a", "b", "c", "d", "e"]
    return render(request, 'func.html', locals())

{% empty %}

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

{% for i in views_list  %}}}
    {{ i }}
{% empty %}
    空列表當然執行~
{% endfor %}

image

include 標籤

{% include %} 標籤允許在模板中包含其它的模板的內容,類似後端導入模組

{% include 'func2.html'%}
# func2.html
<h1>哈哈哈</h1>

image

csrf_token

作用:跨站請求偽造保護。

在我們使用form表單的時候,經常報403許可權錯誤,這裡我們可以在HTML頁面使用{% csrf_token %},表單提交數據才會成功,或者在settings.py將中間件注釋掉也可以;

解析:

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

然後,等用戶需要用到form表單提交數據的時候,會攜帶這個 input 標籤一起提交給中間件 csrf,原因是 form 表單提交數據時,會包括所有的 input 標籤,中間件 csrf 接收到數據時,會判斷,這個隨機字元串是不是第一次它發給用戶的那個,如果是,則數據提交成功,如果不是,則返回403許可權錯誤。

自定義過濾器

1、在應用目錄下創建 templatetags 目錄名只能是 templatetags;

2、在 templatetags 目錄下創建任意 py 文件,如:my_tag.py。

3、my_tag.py 文件程式碼如下:

from django import template

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

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

注意:自定義過濾器也只能接收兩個參數,因為|本質就是前面的參數交給後面過濾器處理,過濾器最強多可自帶一個參數

'''my_tag.py'''
# 自定義過濾器
@register.filter(name='myfilter')
def index(x,y):
    return x * y
'''views.py'''
from django.shortcuts import render
def func(request):
    a=10
    return render(request, 'func.html', locals())

{#載入過濾器#}
{% load my_tag %}
{#使用過濾器#}
{{ a|myfilter:10 }}

image

5、自定義標籤

@register.simple_tag(name='mytag')
def tag(x, y, z):  # 自定義標籤可以接收n個參數
    return x + y + z
{#載入過濾器#}
{% load my_tag %}
{% mytag 1 2 3 %}

image

自定義 inclusion_tag

image

類似將html頁面功能分塊返回了~

自定義inclusion_tag,my_tag.py

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

@register.inclusion_tag('login.html',name='my_inclusion')
def inclusion(n):
    l = []
    for i in range(1,n):
        l.append(f'第{i}頁')

    return locals()  # 將當前名稱空間所有名字返回給login.html

views.py

def func(request):
    return render(request, 'func.html', locals())

lit.py 中間html

<ul>
    {% for foo in l %}
    <li>{{ foo}}</li>
    {% endfor %}
</ul>

func.html

{#載入過濾器#}
{% load my_tag %}
{#生成10個li#}
{% my_inclusion 10 %}

模板繼承

模板可以用繼承的方式來實現復用,減少冗餘內容。

網頁的頭部和尾部內容一般都是一致的,我們就可以通過模板繼承來實現復用。

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

父模板

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

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

子模板

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

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

子模板如果沒有設置父模板預留區域的內容,則使用在父模板設置的默認內容,當然也可以都不設置,就為空。

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

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

子版也可以繼續使用母版劃定區域內的內容

{{ block.super }}

父模板如何劃分區域

劃定區域的時候一般都應該有三個區域:CSS區域,HTML文檔區域、JS區域

這樣劃分區域提高了頁面的可擴展性和方便維護等優點

 {% block css %}
 {% endblock %}
    
 {% block content %}
 {% endblock %}
    
 {% block js %}
 {% endblock %}