04-模板層
一 模版簡介
你可能已經註意到我們在例子視圖中返回文本的方式有點特別。 也就是說,HTML被直接硬編碼在 Python代碼之中。
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
盡管這種技術便於解釋視圖是如何工作的,但直接將HTML硬編碼到你的視圖裏卻並不是一個好主意。 讓我們來看一下為什麽:
-
對頁面設計進行的任何改變都必須對 Python 代碼進行相應的修改。 站點設計的修改往往比底層 Python 代碼的修改要頻繁得多,因此如果可以在不進行 Python 代碼修改的情況下變更設計,那將會方便得多。
-
Python 代碼編寫和 HTML 設計是兩項不同的工作,大多數專業的網站開發環境都將他們分配給不同的人員(甚至不同部門)來完成。 設計者和HTML/CSS的編碼人員不應該被要求去編輯Python的代碼來完成他們的工作。
-
程序員編寫 Python代碼和設計人員制作模板兩項工作同時進行的效率是最高的,遠勝於讓一個人等待另一個人完成對某個既包含 Python又包含 HTML 的文件的編輯工作。
基於這些原因,將頁面的設計和Python的代碼分離開會更幹凈簡潔更容易維護。 我們可以使用 Django的 模板系統 (Template System)來實現這種模式,這就是本章要具體討論的問題
python的模板:HTML代碼+模板語法
def current_time(req): # ================================原始的視圖函數 # import datetime # now=datetime.datetime.now() # html="<html><body>現在時刻:<h1>%s.</h1></body></html>" %now # ================================django模板修改的視圖函數 # from django.template import Template,Context # now=datetime.datetime.now() # t=Template(‘<html><body>現在時刻是:<h1>{{current_date}}</h1></body></html>‘) # #t=get_template(‘current_datetime.html‘) # c=Context({‘current_date‘:str(now)}) # html=t.render(c) # # return HttpResponse(html) #另一種寫法(推薦) import datetime now=datetime.datetime.now() return render(req, ‘current_datetime.html‘, {‘current_date‘:str(now)[:19]})
模版語法重點:
變量:{{ 變量名 }}
1 深度查詢 用句點符
2 過濾器
標簽:{{% % }}
二 模版語法之變量
在 Django 模板中遍歷復雜數據結構的關鍵是句點字符, 語法:{{變量名}}
views.py
def template_test(request): name = ‘lqz‘ li = [‘lqz‘, 1, ‘18‘] dic = {‘name‘: ‘lqz‘, ‘age‘: 18} ll2 = [ {‘name‘: ‘lqz‘, ‘age‘: 18}, {‘name‘: ‘lqz2‘, ‘age‘: 19}, {‘name‘: ‘egon‘, ‘age‘: 20}, {‘name‘: ‘kevin‘, ‘age‘: 23} ] ll3=[] class Person: def __init__(self, name): self.name = name def test(self): print(‘test函數‘) return 11 @classmethod def test_classmethod(cls): print(‘類方法‘) return ‘類方法‘ @staticmethod def static_method(): print(‘靜態方法‘) return ‘靜態方法‘ lqz = Person(‘lqz‘) egon = Person(‘egon‘) person_list = [lqz, egon] bo = True te = test() import datetime now=datetime.datetime.now() link1=‘<a href="https://www.baidu.com">點我<a>‘ from django.utils import safestring link=safestring.mark_safe(link1) # html特殊符號對照表(http://tool.chinaz.com/Tools/htmlchar.aspx) # 這樣傳到前臺不會變成特殊字符,因為django給處理了 dot=‘♠‘ # return render(request, ‘template_index.html‘, {‘name‘:name,‘person_list‘:person_list}) return render(request, ‘template_index.html‘, locals())
html
<p>{{ name }}</p> <p>{{ li }}</p> <p>{{ dic }}</p> <p>{{ lqz }}</p> <p>{{ person_list }}</p> <p>{{ bo }}</p> <p>{{ te }}</p> <hr> <h3>深度查詢句點符</h3> <p>{{ li.1 }}</p> <p>{{ dic.name }}</p> <p>{{ lqz.test }}</p> <p>{{ lqz.name }}</p> <p>{{ person_list.0 }}</p> <p>{{ person_list.1.name }}</p> <hr> <h3>過濾器</h3> {#註意:冒號後面不能加空格#} <p>{{ now | date:"Y-m-d H:i:s" }}</p> {#如果變量為空,設置默認值,空數據,None,變量不存在,都適用#} <p>{{ name |default:‘數據為空‘ }}</p> {#計算長度,只有一個參數#} <p>{{ person_list |length }}</p> {#計算文件大小#} <p>{{ 1024 |filesizeformat }}</p> {#字符串切片,前閉後開,前面取到,後面取不到#} <p>{{ ‘hello world lqz‘ |slice:"2:-1" }}</p> <p>{{ ‘hello world lqz‘ |slice:"2:5" }}</p> {#截斷字符,至少三個起步,因為會有三個省略號(傳負數,1,2,3都是三個省略號)#} <p>{{ ‘劉清政 world lqz‘ |truncatechars:"4" }}</p> {#截斷文字,以空格做區分,這個不算省略號#} <p>{{ ‘劉清政 是 大帥比 謝謝‘ |truncatewords:"1" }}</p> <p>{{ link1 }}</p> <p>{{ link1|safe }}</p> <p>{{ link }}</p> <p>♠</p> <p>{{ dot }}</p> {#add 可以加負數,傳數字字符串都可以#} <p>{{ "10"|add:"-2" }}</p> <p>{{ li.1|add:"-2" }}</p> <p>{{ li.1|add:2 }}</p> <p>{{ li.1|add:"2" }}</p> <p>{{ li.1|add:"-2e" }}</p> {#upper#} <p>{{ name|upper }}</p> <p>{{ ‘LQZ‘|lower }}</p> <hr> <h3>模版語法之標簽</h3> {#for 循環 循環列表,循環字典,循環列表對象#} <ui> {% for foo in dic %} {{ foo }} {% endfor %} {#也可以混用html標簽#} {% for foo in li %} <ul>foo</ul> {% endfor %} </ui> {#表格#} <table border="1"> {% for foo in ll2 %} <tr> <td>{{ foo.name }}</td> <td>{{ foo.age }}</td> </tr> {% endfor %} </table> <table border="1"> {#‘parentloop‘: {}, ‘counter0‘: 0, ‘counter‘: 1, ‘revcounter‘: 4, ‘revcounter0‘: 3, ‘first‘: True, ‘last‘: False}#} {% for foo in ll2 %} <tr> <td>{{ forloop.counter }}</td> <td>{{ foo.name }}</td> <td>{{ foo.age }}</td> </tr> {% endfor %} </table> {% for foo in ll5 %} <p>foo.name</p> {% empty %} <p>空的</p> {% endfor %} <hr> <h3>if判斷</h3> {% if name %} <a href="">hi {{ name }}</a> <a href="">註銷</a> {% else %} <a href="">請登錄</a> <a href="">註冊</a> {% endif %} {#還有elif#} <hr> <h3>with</h3> {% with ll2.0.name as n %} {{ n }} {% endwith %} {{ n }} {% load my_tag_filter %} {{ 3|multi_filter:3 }} {#傳參必須用空格區分#} {% multi_tag 3 9 10 %} {#可以跟if連用#} {% if 3|multi_filter:3 > 9 %} <p>大於</p> {% else %} <p>小於</p> {% endif %}
註意:句點符也可以用來引用對象的方法(無參數方法):
<h4>字典:{{ dic.name.upper }}<
/
h4>
三 模版之過濾器
語法:
{{obj|filter__name:param}} 變量名字|過濾器名稱:變量
default
如果一個變量是false或者為空,使用給定的默認值。否則,使用變量的值。例如:
1 |
{{ value|default: "nothing" }}
|
length
返回值的長度。它對字符串和列表都起作用。例如:
1 |
{{ value|length }}
|
如果 value 是 [‘a‘, ‘b‘, ‘c‘, ‘d‘],那麽輸出是 4。
filesizeformat
將值格式化為一個 “人類可讀的” 文件尺寸 (例如 ‘13 KB‘
, ‘4.1 MB‘
, ‘102 bytes‘
, 等等)。例如:
1 |
{{ value|filesizeformat }}
|
如果 value
是 123456789,輸出將會是 117.7 MB
。
date
如果 value=datetime.datetime.now()
1 |
{{ value|date: "Y-m-d" }}
|
slice
如果 value="hello world"
1 |
{{ value| slice : "2:-1" }}
|
truncatechars
如果字符串字符多於指定的字符數量,那麽會被截斷。截斷的字符串將以可翻譯的省略號序列(“...”)結尾。
參數:要截斷的字符數
例如:
1 |
{{ value|truncatechars: 9 }}
|
safe
Django的模板中會對HTML標簽和JS等語法標簽進行自動轉義,原因顯而易見,這樣是為了安全。但是有的時候我們可能不希望這些HTML元素被轉義,比如我們做一個內容管理系統,後臺添加的文章中是經過修飾的,這些修飾可能是通過一個類似於FCKeditor編輯加註了HTML修飾符的文本,如果自動轉義的話顯示的就是保護HTML標簽的源文件。為了在Django中關閉HTML的自動轉義有兩種方式,如果是一個單獨的變量我們可以通過過濾器“|safe”的方式告訴Django這段代碼是安全的不必轉義。比如:
1 |
value = "<a href=" ">點擊</a>"
|
1 |
{{ value|safe}}
|
其它過濾器(了解)
過濾器 | 描述 | 示例 |
upper | 以大寫方式輸出 | {{ user.name | upper }} |
add | 給value加上一個數值 | {{ user.age | add:”5” }} |
addslashes | 單引號加上轉義號 | |
capfirst | 第一個字母大寫 | {{ ‘good’| capfirst }} 返回”Good” |
center | 輸出指定長度的字符串,把變量居中 | {{ “abcd”| center:”50” }} |
cut | 刪除指定字符串 | {{ “You are not a Englishman” | cut:”not” }} |
date | 格式化日期 | |
default | 如果值不存在,則使用默認值代替 | {{ value | default:”(N/A)” }} |
default_if_none | 如果值為None, 則使用默認值代替 | |
dictsort | 按某字段排序,變量必須是一個dictionary | {% for moment in moments | dictsort:”id” %} |
dictsortreversed | 按某字段倒序排序,變量必須是dictionary | |
divisibleby | 判斷是否可以被數字整除 |
{{ 224 | divisibleby:2 }} 返回 True |
escape | 按HTML轉義,比如將”<”轉換為”<” | |
filesizeformat | 增加數字的可讀性,轉換結果為13KB,89MB,3Bytes等 |
{{ 1024 | filesizeformat }} 返回 1.0KB |
first | 返回列表的第1個元素,變量必須是一個列表 | |
floatformat | 轉換為指定精度的小數,默認保留1位小數 | {{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入 |
get_digit | 從個位數開始截取指定位置的數字 | {{ 123456 | get_digit:’1’}} |
join | 用指定分隔符連接列表 | {{ [‘abc’,’45’] | join:’*’ }} 返回 abc*45 |
length | 返回列表中元素的個數或字符串長度 | |
length_is | 檢查列表,字符串長度是否符合指定的值 | {{ ‘hello’| length_is:’3’ }} |
linebreaks | 用<p>或<br>標簽包裹變量 | {{ “Hi\n\nDavid”|linebreaks }} 返回<p>Hi</p><p>David</p> |
linebreaksbr | 用<br/>標簽代替換行符 | |
linenumbers | 為變量中的每一行加上行號 | |
ljust | 輸出指定長度的字符串,變量左對齊 | {{‘ab’|ljust:5}}返回 ‘ab ’ |
lower | 字符串變小寫 | |
make_list | 將字符串轉換為列表 | |
pluralize | 根據數字確定是否輸出英文復數符號 | |
random | 返回列表的隨機一項 | |
removetags | 刪除字符串中指定的HTML標記 | {{value | removetags: “h1 h2”}} |
rjust | 輸出指定長度的字符串,變量右對齊 | |
slice | 切片操作, 返回列表 | {{[3,9,1] | slice:’:2’}} 返回 [3,9]{{ ‘asdikfjhihgie‘ | slice:‘:5‘ }} 返回 ‘asdik’ |
slugify | 在字符串中留下減號和下劃線,其它符號刪除,空格用減號替換 |
{{ ‘5-2=3and5 2=3‘ | slugify }} 返回 5-23and5-23 |
stringformat | 字符串格式化,語法同python | |
time | 返回日期的時間部分 | |
timesince | 以“到現在為止過了多長時間”顯示時間變量 | 結果可能為 45days, 3 hours |
timeuntil | 以“從現在開始到時間變量”還有多長時間顯示時間變量 | |
title | 每個單詞首字母大寫 | |
truncatewords | 將字符串轉換為省略表達方式 |
{{ ‘This is a pen‘ | truncatewords:2 }}返回 This is ... |
truncatewords_html | 同上,但保留其中的HTML標簽 |
{{ ‘<p>This is a pen</p>‘ | truncatewords:2 }}返回 <p>This is ...</p> |
urlencode | 將字符串中的特殊字符轉換為url兼容表達方式 | {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}} |
urlize | 將變量字符串中的url由純文本變為鏈接 | |
wordcount | 返回變量字符串中的單詞數 | |
yesno | 將布爾變量轉換為字符串yes, no 或maybe |
{{ True | yesno }} 返回 yes no maybe |
回到目錄
四 模版之標簽