為什么用templates?
views.py視圖函數是用來寫Python代碼的,HTML可以被直接硬編碼在views.py之中。如下:
import datetime def current_time(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
-
對頁面設計進行的任何改變都必須對 Python views.py中的代碼進行相應的修改。 站點設計的修改往往比底層 Python 代碼的修改要頻繁得多,因此如果可以在不進行 Python 代碼修改的情況下變更設計,那將會方便得多。
-
Python 代碼編寫和 HTML 設計是兩項不同的工作,大多數專業的網站開發環境都將他們分配給不同的人員(甚至不同部門)來完成。 設計者和HTML/CSS的編碼人員不應該被要求去編輯Python的代碼來完成他們的工作。
-
程序員編寫 Python代碼和設計人員制作模板兩項工作同時進行的效率是最高的,遠勝於讓一個人等待另一個人完成對某個既包含 Python又包含 HTML 的文件的編輯工作。
基於這些原因,將頁面的設計和Python的代碼分離開會更干凈簡潔更容易維護。 我們可以使用 Django的 模板系統 (Template System)來實現這種模式。
1.配置settings.py
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
2.templates模板組成
HTML代碼+邏輯控制代碼
你使用過一些在HTML中直接混入程序代碼的語言,現在,Django的模版系統並不是簡單的將Python嵌入到HTML中。
設計決定了:模版系統致力於表達外觀,而不是程序邏輯。
Django的模版系統提供了和某些程序架構類似的標簽——用於布爾判斷的 if 標簽, 用於循環的 for 標簽等等。
——但是這些都不是簡單的作為Python代碼那樣來執行的,並且,模版系統也不會隨意執行Python表達式。
只有下面列表中的標簽、過濾器和語法才是默認就被支持的。(但是您也可以根據需要添加您自己的擴展到模版語言中)。
2.1 變量
變量: {{ variable }}
點號(.)用來訪問變量的屬性。
當模版系統遇到點("."),它將以這樣的順序查詢:
- 字典查詢(Dictionary lookup)
- 屬性或方法查詢(Attribute or method lookup)
- 數字索引查詢(Numeric index lookup)
>>> python manange.py shell (進入該django項目的環境) >>> from django.template import Context, Template >>> t = Template('My name is {{ name }}.') >>> c = Context({'name': 'Gregory'}) >>> t.render(c) 'My name is Gregory.'
同一模板,多個上下文,一旦有了模板對象,你就可以通過它渲染多個context,無論何時我們都可以,像這樣使用同一模板源渲染多個context,只進行 一次模板創建然后多次調用render()方法渲染會 更為高效:
t = Template('Hello, {{ name }}') for name in ('John', 'Julie', 'Pat'): print(t.render(Context({'name': name})))
在 Django 模板中遍歷復雜數據結構的關鍵是句點字符 (.)
#最好是用幾個例子來說明一下。
# 首先,句點可用於訪問列表索引,例如:
>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
'Item 2 is carrots.'
#假設你要向模板傳遞一個 Python 字典。 要通過字典鍵訪問該字典的值,可使用一個句點:
>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
'Sally is 43 years old.'
#同樣,也可以通過句點來訪問對象的屬性。 比方說, Python 的 datetime.date 對象有
#year 、 month 和 day 幾個屬性,你同樣可以在模板中使用句點來訪問這些屬性:
>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)
'The month is 5 and the year is 1993.'
# 這個例子使用了一個自定義的類,演示了通過實例變量加一點(dots)來訪問它的屬性,這個方法適
# 用於任意的對象。
>>> from django.template import Template, Context
>>> class Person(object):
... def __init__(self, first_name, last_name):
... self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
'Hello, John Smith.'
# 點語法也可以用來引用對象的方法。 例如,每個 Python 字符串都有 upper() 和 isdigit()
# 方法,你在模板中可以使用同樣的句點語法來調用它們:
>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
'hello -- HELLO -- False'
>>> t.render(Context({'var': '123'}))
'123 -- 123 -- True'
# 注意這里調用方法時並* 沒有* 使用圓括號 而且也無法給該方法傳遞參數;你只能調用不需參數的
# 方法。
2.2 過濾器
您可以通過使用 過濾器來改變變量的顯示。
{{ name|lower }}。這將在變量 {{ name }} 被過濾器 lower 過濾后再顯示它的值,該過濾器將文本轉換成小寫。使用管道符號 (|)來應用過濾器。
過濾管道可以被* 套接* ,既是說,一個過濾器管道的輸出又可以作為下一個管道的輸入:
1
|
{{ my_list|first|upper }} 將第一個元素並將其轉化為大寫。
|
內置過濾器:
add——把add后的參數加給value
{{ value|add:"2" }} 如果 value 為 4,則會輸出 6. 過濾器首先會強制把兩個值轉換成Int類型。如果強制轉換失敗, 它會試圖使用各種方式吧兩個值相加。它會使用一些數據類型 (字符串, 列表, 等等.)
last 返回列表中的最后一個項目。
{{ value|last }} If value is the list ['a', 'b', 'c', 'd'], the output will be the string "d".
length 返回值的長度。
{{ value|length }}如果value是['a', 'b', 'c', 'd']或"abcd",輸出將為4。
1 add : 給變量加上相應的值 2 addslashes : 給變量中的引號前加上斜線 3 capfirst : 首字母大寫 4 cut : 從字符串中移除指定的字符 5 date : 格式化日期字符串 6 default : 如果值是False,就替換成設置的默認值,否則就是用本來的值 7 default_if_none: 如果值是None,就替換成設置的默認值,否則就使用本來的值
2.3 標簽 {% tag %}
{% for %} 允許我們在一個序列上迭代。
{% for a in a_list %} <li>{{ a.name }}</li> {% endfor %}
根據條件判斷是否輸出。if/else 支持嵌套。{% if %} 標簽接受 and , or 或者 not 關鍵字來對多個變量做判斷 ,或者對變量取反( not ),例如:
1
2
3
|
{%
if
a_list and c_list %}
a 和 c變量都是可用的。
{% endif %}
|
注釋標簽——要注釋模版中一行的部分內容,使用注釋語法 {# #}.
{%csrf_token%}:csrf_token標簽
用於生成csrf_token的標簽,用於防治跨站攻擊驗證。注意如果你在view的index里用的是render_to_response方法,不會生效
其實,這里是會生成一個input標簽,和其他表單標簽一起提交給后台的。
<form action="{% url "bieming"%}" > <input type="text"> <input type="submit"value="提交"> {%csrf_token%} </form>
{% url %}: 引用路由配置的地址
{% with %}:用更簡單的變量名替代復雜的變量名
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
{% verbatim %}: 禁止render
{% verbatim %}
{{ hello }}
{% endverbatim %}
{% load %}: 加載標簽庫
{% include %} 標簽允許在模板中包含其它的模板的內容。
2.4 自定義模板標簽和過濾器
a、在app中創建templatetags模塊(必須的)
app/ __init__.py models.py templatetags/ __init__.py mytag.py views.py
使用{% load mytag %}
b、創建任意 .py 文件,如:mytag.py
為了成為一個可用的標簽庫,這個模塊必須包含一個名為 register的變量,它是template.Library 的一個實例,所有的標簽和過濾器都是在其中注冊的。所以把如下的內容放在你的模塊的頂部:
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
@register.filter def filter_multi(v1,v2): return v1 * v2 @register.simple_tag def simple_tag_multi(v1,v2): return v1 * v2 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
c、在使用自定義simple_tag和filter的html文件中導入之前創建的 my_tags.py :{% load mytag %}
d、使用simple_tag和filter(如何調用)
{% load xxx %} #首行 # num=12 {{ num|filter_multi:2 }} #24 {{ num|filter_multi:"[22,333,4444]" }} {% simple_tag_multi 2 5 %} 參數不限,但不能放在if for語句中 {% simple_tag_multi num 5 %}
2.5模版繼承
模版繼承可以讓您創建一個基本的“骨架”模版,它包含您站點中的全部元素,並且可以定義能夠被子模版覆蓋的 blocks 。
base.html

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 body{ 8 margin: 0; 9 } 10 .hide{ 11 display: none; 12 } 13 .menu .item{ 14 display: block; 15 padding: 5px 10px; 16 border-bottom: 1px solid #dddddd; 17 } 18 .menu .item:hover{ 19 background-color: black; 20 color: white; 21 } 22 .menu .item.active{ 23 background-color: black; 24 color: white; 25 } 26 27 .modal{ 28 position: fixed; 29 top: 50%; 30 left: 50%; 31 width: 500px; 32 height: 400px; 33 margin-top: -250px; 34 margin-left: -250px; 35 z-index: 100; 36 background-color: white; 37 } 38 .remove{ 39 position: fixed; 40 top: 50%; 41 left: 50%; 42 width: 400px; 43 height: 200px; 44 margin-top: -100px; 45 margin-left: -200px; 46 z-index: 100; 47 background-color: #c00; 48 } 49 .shade{ 50 position: fixed; 51 top: 0; 52 left: 0; 53 right: 0; 54 bottom: 0; 55 background-color: black; 56 opacity: 0.5; 57 z-index: 99; 58 } 59 .pagination a{ 60 display: inline-block; 61 padding: 5px; 62 } 63 .pagination a.active{ 64 background-color: black; 65 color: white; 66 } 67 </style> 68 {% block css %} {% endblock %} 69 </head> 70 <body> 71 <div style="height: 48px;background-color: black;color: white"> 72 <div style="float: right">用戶名:{{ username }} | <a href="/logout.html">注銷</a></div> 73 </div> 74 75 <div> 76 <div class="menu" style="position: absolute;top: 48px;left: 0;bottom:0;width: 200px;background-color: #eeeeee"> 77 <a id="menu_class" class="item" href="/classes.html">班級管理</a> 78 <a id="menu_student" class="item" href="/student.html">學生管理</a> 79 <a id="menu_teacher" class="item" href="/teacher.html">老師管理</a> 80 </div> 81 <div style="position: absolute;top: 48px;left: 200px;bottom:0;right: 0;overflow: auto"> 82 83 {% block content %} {% endblock %} 84 85 </div> 86 </div> 87 <script src="/static/jquery-2.1.4.min.js"></script> 88 {% block js %} {% endblock %} 89 </body> 90 </html>
block 標簽定義了三個可以被子模版內容填充的block。 block 告訴模版引擎: 子模版可能會覆蓋掉模版中的這些位置。
{% block css %} {% endblock %}
{% block content %} {% endblock %}
{% block js %} {% endblock %}
{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>添加班級</h1> <form action="/add_classes.html" method="POST"> <input type="text" name="caption" /> <input type="submit" value="提交"/>{{ msg }} </form> {% endblock %} {% block js %} <script> $(function () { $('#menu_class').addClass('active'); }); </script> {% endblock %}
extends 標簽是這里的關鍵。它告訴模版引擎,這個模版“繼承”了另一個模版。