一.使用模板的原因
-
對頁面設計進行的任何改變都必須對 Python 代碼進行相應的修改。 站點設計的修改往往比底層 Python 代碼的修改要頻繁得多,因此如果可以在不進行 Python 代碼修改的情況下變更設計,那將會方便得多。
-
Python 代碼編寫和 HTML 設計是兩項不同的工作,大多數專業的網站開發環境都將他們分配給不同的人員(甚至不同部門)來完成。 設計者和HTML/CSS的編碼人員不應該被要求去編輯Python的代碼來完成他們的工作。
-
程序員編寫 Python代碼和設計人員制作模板兩項工作同時進行的效率是最高的,遠勝於讓一個人等待另一個人完成對某個既包含 Python又包含 HTML 的文件的編輯工作。
二.Python 模板定義
html+模板語法
模版包括在使用時會被值替換掉的 變量,和控制模版邏輯的標簽。
注意:
在 Django 模板中遍歷復雜數據結構的關鍵是句點字符 .
示例:
#views.py 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 person_yuan=Person("yuan") # 自定義類對象 person_egon=Person("egon") person_alex=Person("alex") person_list=[person_yuan,person_egon,person_alex] return render(request,"index.html",{"l":l,"dic":dic,"date":date,"person_list":person_list}) #xxx.html <h4>{{s}}</h4> <h4>列表:{{ l.0 }}</h4> <h4>列表:{{ l.2 }}</h4> <h4>字典:{{ dic.name }}</h4> <h4>日期:{{ date.year }}</h4> <h4>類對象列表:{{ person_list.0.name }}</h4>
三.模板之過濾器
語法:{{obj|filter__name:param}}
default
#如果一個變量是false或者為空,使用給定的默認值。否則,使用變量的值。例: {{ value|default:"nothing" }}
length
返回值的長度。它對字符串和列表都起作用。例: {{ value|length }} #如果 value 是 ['a', 'b', 'c', 'd'],那么輸出是 4
filesizeformat
#將值格式化為一個 “人類可讀的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等) {{ value|filesizeformat }} #如果 value 是 123456789,輸出將會是 117.7 MB
date
#如果 value=datetime.datetime.now() {{ value|date:"Y-m-d" }}
slice
#如果 value="hello world" {{ value|slice:"2:-1" }}
truncatechars
#參數:要截斷的字符數 {{ value|truncatechars:9 }}
safe
Django的模板中會對HTML標簽和JS等語法標簽進行自動轉義,原因顯而易見,這樣是為了安全。但是有的時候我們可能不希望這些HTML元素被轉義,為了在Django中關閉HTML的自動轉義有兩種方式,如果是一個單獨的變量我們可以通過過濾器“|safe”的方式告訴Django這段代碼是安全的不必轉義。
value="<a href="">點擊</a>" {{ value|safe}}
四.模板之標簽
標簽比變量更加復雜:一些在輸出中創建文本,一些通過循環或邏輯來控制流程,一些加載其后的變量將使用到的額外信息到模版中。一些標簽需要開始和結束標簽 (例如{% tag %} ...
標簽 內容 ... {% endtag %})。
for標簽
示例:
#遍歷列表 {% 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.counter The current iteration of the loop (1-indexed) forloop.counter0 The current iteration of the loop (0-indexed) forloop.revcounter The number of iterations from the end of the loop (1-indexed) forloop.revcounter0 The number of iterations from the end of the loop (0-indexed) forloop.first True if this is the first time through the loop forloop.last True if this is the last time through the loop
for...empty
在給出的組是空的或者沒有被找到時,可以有所操作
示例:
{% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
if 標簽
{% if %}會對一個變量求值,如果它的值是“True”(存在、不為空、且不是boolean類型的false值),對應的內容塊會輸出。
{% if num > 100 or num < 0 %} <p>無效</p> {% elif num > 80 and num < 100 %} <p>優秀</p> {% else %} <p>差</p> {% endif %}
with 標簽
使用一個簡單地名字緩存一個復雜的變量,當你需要使用一個“昂貴的”方法(比如訪問數據庫)很多次的時候是非常有用的。
示例:
{% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %}
csrf_token 這個標簽用於跨站請求偽造保護
五.自定義標簽和過濾器
步驟: 1 在settings中的INSTALLED_APPS,是否有當前應用 2 在應用中創建一個templatetags 3 在templatetags中創建py文件:mytag.py 4 在mytag.py中: 引入: from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改變 5 定義過濾器和標簽 @register.filter def multi(x,y): return x*y @register.simple_tag def multiTag(x,y,z): return x*y*z 6 在引用模板中導入:{% load myTag %} 7 調用: 過濾器: {{var|filter_name:參數}} # 參數只能是一個 標簽: {% simple_tag 參數1 參數2 ... %} 對比過濾器與自定義標簽的使用: 過濾器函數的參數只能有兩個,自定義標簽無參數限制 過濾器可以與邏輯標簽共同使用,比如if標簽。自定義標簽不可以。 注:filter可以用在if等語句后,simple_tag不可以 {% if num|filter_multi:30 > 100 %} {{ num|filter_multi:30 }} {% endif %}
六.模版繼承(extend)
為什么要用繼承?
在實際的WEB開發中,經常需要對站點的公用部分進行重載,而僅對頁面部分內容進行修改(比如首頁),如果不用繼承,就需要寫大量重復代碼,為了避免寫大量重復代碼,所以用到了模版繼承
實例:
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title>{% block title %}My amazing site{%/span> endblock %}</title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block content %}{% endblock %} </div> </body> </html>
這個模版,我們把它叫作 base.html
, 它定義了一個可以用於兩列排版頁面的簡單HTML骨架。“子模版”的工作是用它們的內容填充空的blocks。
子模版
{% extends "base.html" %} {% block title %}My amazing blog{% endblock %} {% block content %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
在這個例子中, block
標簽定義了三個可以被子模版內容填充的block。 block
告訴模版引擎: 子模版可能會覆蓋掉模版中的這些位置。
輸出效果:
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title>My amazing blog</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> </div> <div id="content"> <h2>Entry one</h2> <p>This is my first entry.</p> <h2>Entry two</h2> <p>This is my second entry.</p> </div> </body> </html>
注意:
-
如果你在模版中使用
{% extends %}
標簽,它必須是模版中的第一個標簽。其他的任何情況下,模版繼承都將無法工作。 -
在base模版中設置越多的
{% block %}
標簽越好。請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數blocks中填充合理的默認內容,然后,只定義你需要的那一個。多一點鈎子總比少一點好。 -
如果你發現你自己在大量的模版中復制內容,那可能意味着你應該把內容移動到父模版中的一個
{% block %}
中。 -
If you need to get the content of the block from the parent template, the
{{ block.super }}
variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using{{ block.super }}
will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template. -
為了更好的可讀性,你也可以給你的
{% endblock %}
標簽一個 名字 。例如:
{% block content %}
...
{% endblock content %}
-
在大型模版中,這個方法幫你清楚的看到哪一個
{% block %}
標簽被關閉了。
最后,請注意您並不能在一個模版中定義多個相同名字的 block
標簽。這個限制的存在是因為block標簽的作用是“雙向”的。這個意思是,block標簽不僅提供了一個坑去填,它還在 _父模版_中定義了填坑的內容。如果在一個模版中有兩個名字一樣的 block
標簽,模版的父模版將不知道使用哪個block的內容。