第六篇:Django之模板層
第六篇:Django之模板層
目錄一、模板語法傳值
模板語法簡單來說,只有兩種兩種格式。
# 第一種
{{ }}:變數相關
# 第二種
{% %}:邏輯相關
模板語法可以傳遞後端的python資料型別給html頁面。
下面我們進行一一測試python的資料型別是否可以通過模板語法傳遞。
我們在後端設定這樣的資料,用來進行測試。
# 模板語法 def index(request): # 我們先定義python中的資料型別 num = 111 flo = 222.2 bo = True li = ['楊毅', '雷超', '安安', '楊鑫', '權康', '港川'] tup = ('小紅', '小花', '小蘭', '小紫', '小綠') dic = {'username': '楊毅', 'age': 18, 'gender': '男'} se = {'張無忌', '趙敏', '周芷若'} def func(): return ('俺被執行了') class MyClass(object): def get_self(self): return '繫結方法' @staticmethod def get_func(): return '靜態方法' @classmethod def get_class(cls): return '類方法' # 物件被展示到html頁面上 就類似於執行了列印操作也會觸發__str__方法 def __str__(self): return '到底會不會執行呢?' obj = MyClass() return render(request, 'index.html', locals())
我們的index.html頁面中如此書寫。
<p>整形:{{ num }}</p> <p>浮點型:{{ flo }}</p> <p>布林值:{{ bo }}</p> <p>列表:{{ li }}</p> <p>元組:{{ tup }}</p> <p>字典:{{ dic }}</p> <p>集合:{{ se }}</p> <p>函式:{{ func }}</p> <p>類:{{ MyClass }}</p> <p>物件:{{ obj }}</p> <p>物件呼叫繫結方法:{{ obj.get_self }}</p> <p>物件呼叫類方法:{{ obj.get_class }}</p> <p>物件呼叫靜態方法:{{ obj.get_func }}</p>
之後我們便可以在瀏覽器中渲染出這樣的結果。
注意:
1、傳遞函式名會自動加括號呼叫,但是模版語法不支援給函式傳額外的引數。【顯示的是函式的返回值】
2、傳類名的時候也會自動加括號呼叫(例項化)
3、模板語法內部能夠自動判斷出當前的變數名是否可以加括號呼叫,如果可以就會自動執行。【針對的是函式名和類名】
Django模板語法取值的取值
django模版語法的取值,是固定的格式,只能採用“句點符” 。【也可以點索引,真是天才呀,哈哈。】
<p>{{ d.username }}</p> <p>{{ l.0 }}</p> <p>{{ d.hobby.3.info }}</p> # 即可以點鍵也可以點索引 還可以兩者混用 """與jinja2模板語法不同""" # jinja2模板語法和python語法極為類似。 """ jinja2模板語法 {{ user }} {{ user.get('username')}} {{ user.age }} {{ user['hobby'] }} """
二、模版語法之過濾器
過濾器就類似於是模版語法內建的內建方法,django內建有60多個過濾器,在這裡,我們只需要瞭解10多個就足矣。日後碰見在進行記憶。
基本語法:
{{資料|過濾器:引數}}
使用方式:
"""我們views.py中這樣設定"""
# 模板語法
def index(request):
msg = 'my name is yang and my age is 18'
is_true = False
file_size = 123465798
current_time = datetime.datetime.now()
li = ['新垣結衣', '石原里美', '迪麗熱巴', '佟麗婭']
info = '任時光匆匆離去,我只在乎你,心甘情願感受你的呼吸。'
num = 100
s = 'hello, '
h5 = '<h1>迪麗熱巴</h1>'
js = '<script>alert("迪麗熱巴")</script>'
from django.utils.safestring import mark_safe
res = mark_safe('<h1>新垣結衣</h1>')
return render(request, 'index.html', locals())
"""index.html中進行測試"""
# 內部就是len(msg)
<p>統計長度:{{ msg|length }}</p> # 統計長度:32
# 第一個引數布林值是True就展示第一個引數的值,否則展示冒號後面的值
<p>預設值:{{ is_true|default:'啥也不是' }}</p> # 預設值:啥也不是
# 檔案大小【可以自動進行格式轉化】
<p>檔案大小:{{ file_size|filesizeformat }}</p> # 檔案大小:117.7 MB
# 日期格式化
<p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p> # 日期格式化:2021-06-28 16:46:38
# 切片操作(支援步長)
<p>切片操作(支援步長):{{ li|slice:'0:4:2' }}</p> # 切片操作(支援步長):['新垣結衣', '迪麗熱巴']
# 切取字元(包含三個點)
<p>切取字元(包含三個點):{{ info|truncatechars:9 }}</p> # 切取字元(包含三個點):任時光匆匆離...
# 切取單詞(不包含三個點 按照空格切)
<p>切取單詞(不包含三個點 按照空格切):{{ msg|truncatewords:4 }}</p> # 切取單詞(不包含三個點 按照空格切):my name is yang ...
# 移除特定的字元
<p>移除特定的字元:{{ msg|cut:' ' }}</p> # 移除特定的字元:mynameisyangandmyageis18
# 拼接操作
<p>拼接操作:{{ li|join:'$' }}</p> # 拼接操作:新垣結衣$石原里美$迪麗熱巴$佟麗婭
# 拼接操作(加法)
<p>拼接操作(加法):{{ num|add:10 }}</p> # 拼接操作(加法):110
<p>拼接操作(加法):{{ s|add:msg }}</p> # 拼接操作(加法):hello, my name is yang and my age is 18
# 轉義
"""前端"""
<p>轉義(html):{{ h5|safe }}</p> # safe表示告訴瀏覽器是安全的,可以轉義
<p>轉義(js):{{ js|safe }}</p> # js程式碼會先執行
"""後端"""
from django.utils.safestring import mark_safe
res = mark_safe('<h1>新垣結衣</h1>')
"""前端接收"""
<p>後端直接傳過來轉義資料:{{ res }}</p>
index.html中輸出的效果如下。
三、模版語法之標籤
-
for迴圈
我們在index.html中這樣進行書寫。
{% for foo in li %}
<p>{{ forloop }}</p>
{% endfor %}
我們發現在瀏覽器中的到這樣的資料【我們可以使用這些引數進行一定的操作】。
之後,我們可以這樣進行for迴圈。
{% for foo in li %}
<p>{{ foo }}</p>
{% endfor %}
- if判斷
{% if a %}
...
{% elif b %}
...
{% else %}
...
{% endif %}
- for和if混合使用
{% for foo in li %}
{% if forloop.first %}
<p>這是第一次</p>
{% elif forloop.last %}
<p>這是最後一次</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% endfor %}
"""{% empty %} 如果for迴圈的可迭代物件內部沒有元素,則執行"""
{% for foo in list1 %} # list1 = []
{% if forloop.first %}
<p>這是第一次</p>
{% elif forloop.last %}
<p>這是最後一次</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% empty %}
<p>for迴圈的可迭代物件內部沒有元素,根本沒法迴圈</p>
{% endfor %}
效果顯示如下。
- 處理字典
# d.keys 模板語法函式自動執行
{% for foo in d.keys %}
<p>{{ foo }}</p>
{% endfor %}
# d.values
{% for foo in d.values %}
<p>{{ foo }}</p>
{% endfor %}
# d.items
{% for foo in d.items %}
<p>{{ foo }}</p>
{% endfor %}
-
with起別名
在with語法內就可以通過as後面的別名快速的使用到前面非常複雜獲取資料的方式。
{% with li.2 as beauty %} # 通過索引取值
<p>{{ beauty }}</p>
<p>{{ li.2 }}</p>
{% endwith %}
效果如下。
四、自定義過濾器、標籤及inclusion_tag
"""
先三步走
1.在應用下建立一個名字”必須“叫templatetags資料夾
2.在該資料夾內建立“任意”名稱的py檔案 eg:mytag.py
3.在該py檔案內"必須"先書寫下面兩句話(單詞一個都不能錯)
from django import template
register = template.Library()
"""
- 自定義過濾器
"""mytag.py"""
# 自定義過濾器(引數最多兩個)【如果需要多個引數,可以'111 222'字元,不能是列表】
@register.filter(name='baby')
def my_sum(v1, v2):
return v1 + v2
# 使用
{% load mytag %} # 載入頁面
<p>{{ n|baby:666 }}</p>
- 自定義標籤
# 自定義標籤(引數可以有多個)【類似於自定義函式】
@register.simple_tag(name='plus')
def index(a,b,c,d):
return '%s-%s-%s-%s'%(a,b,c,d)
# 使用
標籤多個引數彼此之間空格隔開
<p>{% plus 'yangyi' 123 123 123 %}</p>
- 自定義inclusion_tag
"""
內部原理
1、先定義一個方法
2、在頁面上呼叫該方法,並且可以傳值
3、該方法會生成一些資料然後傳遞給一個html頁面
4、之後將渲染好的結果放到呼叫的位置
"""
"""mytag.py"""
@register.inclusion_tag('left_menu.html')
def left(n):
data = ['第{}項'.format(i) for i in range(n)]
# 第一種
# return {'data':data} # 將data傳遞給left_menu.html
# 第二種
return locals() # 將data傳遞給left_menu.html
"""left_menu.html"""
<ul>
{% for foo in data %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
"""使用"""
{% left 5 %}
# 總結:當html頁面某一個地方的頁面需要傳引數才能夠動態的渲染出來,並且在多個頁面上都需要使用到該區域性,那麼就考慮將該區域性頁面做成inclusion_tag形式。
五、模版的繼承
我們可以在瀏覽一些網站的時候觀察到,有些網站的整體都是大差不差的,只有一些區域性在進行變化。【當然,不使用模板的繼承也沒有問題,只不過程式碼過於冗餘】
我們先簡單建立頁面,樣式如下。訪問地址為127.0.0.1:8000/home/
我們可以在127.0.0.1:8000/reg
和127.0.0.1:8000/login
的html頁面中,簡單的繼承home.html頁面,方式如下。
"""reg.html"""
{% extends 'home.html' %}
"""login.html"""
{% extends 'home.html' %}
如此一來,我們會發現訪問reg和login的頁面和home一樣。
如何進行操作呢?我們可以使用block
將要修改的區域進行重新命名。。
{% block content %} # 將這塊區域重新命名為 content
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}
那麼我們在reg.html和login.html中這樣進行操作即可。
"""reg.html"""
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">使用者註冊</h1>
<form action="" method="post">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="password" class="form-control"></p>
<input type="submit" class="btn btn-success btn-block" value="註冊">
</form>
{% endblock %}
"""login.html"""
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">使用者登入</h1>
<form action="" method="post">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="password" class="form-control"></p>
<input type="submit" class="btn btn-danger btn-block" value="登入">
</form>
{% endblock %}
即可實現實現下面效果。
同時,一般情況下模版頁面上應該至少有三塊可以被修改的區域,包括html區域、css區域和js區域。【每一個子頁面就都可以有自己獨有的css程式碼 html程式碼 js程式碼】,所以我們可以進行優化。
在要被繼承的html檔案中,事先劃分好要被繼承的區域。
"""home.html"""
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
"""reg.html"""
{% extends 'home.html' %}
{% block css %}
<style>
body {
background-color: wheat;
}
</style>
{% endblock %}
{% block content %}
<h1 class="text-center">使用者註冊</h1>
<form action="" method="post">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="password" class="form-control"></p>
<input type="submit" class="btn btn-success btn-block" value="註冊">
</form>
{% endblock %}
{% block js %}
<script>
alert('註冊頁面')
</script>
{% endblock %}
"""login.html"""
{% extends 'home.html' %}
{% block css %}
<style>
body {
background-color: olivedrab;
}
</style>
{% endblock %}
{% block content %}
<h1 class="text-center">使用者登入</h1>
<form action="" method="post">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="password" class="form-control"></p>
<input type="submit" class="btn btn-danger btn-block" value="登入">
</form>
{% endblock %}
{% block js %}
<script>
alert('登入頁面')
</script>
{% endblock %}
由此可以實現下述效果。
補充:一般情況下,模版的頁面上劃定的區域越多,那麼該模版的擴充套件性就越高
但是如果太多,那還不如自己直接重寫。
六、模版的匯入
可以將html檔案當作一個模組,將區域性html程式碼寫入其中,需要的時候直接匯入即可使用。
"""新建一個new.html資料夾,其中存放"""
<h1>這是一個form表單</h1>
# 匯入方式
{% include 'wasai.html' %}