4.Django基於模板頁面
在前一章中,HTML是直接被硬編碼在 Python views.py代碼中,如下:
from django.http import HttpResponse import datetime def hello(request): return HttpResponse("Hello world") def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
在實際的項目開發中,站點頁面設計的修改往往比底層 Python 代碼的修改要頻繁得多,如果每次對頁面設計所進行的任何改變都必須對底層Python 代碼進行相應的修改,是很難滿足實際的項目開發需要的。因此, Django開發了一套模板系統 (Template System)來實現將頁面的設計和Python的代碼分離開的開發模式,本章節我們只通過簡單的實例來說明模板系統如何運用,具體的模板系統的語法和原理,請參考《The Django Book》網站。
Django模板是一個文本,用於分離文檔的表現形式和內容。 模板定義了占位符以及各種用於規范文檔該如何顯示的各部分基本邏輯(模板標簽)。 模板通常用於產生HTML,但是Django的模板也可以產生任何基於文本格式的文檔。
4.1.如何使用模板系統
在Python代碼中使用Django模板的最基本方式如下:
- 可以用原始的模板代碼字符串創建一個 Template 對象,同樣Django也支持用指定模板文件路徑的方式來創建 Template 對象;
- 調用模板對象的render方法,並且傳入一套變量context。它將返回一個基於模板的展現字符串,模板中的變量和標簽會被context值替換。
>>> from django import template >>> t = template.Template('My name is {{ name }}.') >>> c = template.Context({'name': 'Haozi'}) >>> print t.render(c) My name is Haozi. >>> c = template.Context({'name': 'Wuch'}) >>> print t.render(c) My name is Wuch.
4.1.1. 創建模板對象
創建一個 Template 對象的方法就是直接實例化它。 Template 類就在 django.template 模塊中,構造函數接受一個“原始模板代碼”作為參數。
4.1.2. 模板渲染
一旦創建一個 Template 對象,就可以用 context 來傳遞數據給它。 一個context是一系列變量和它們值的集合。
>>> from django.template import Context, Template >>> t = Template('My name is {{ name }}.') >>> c = Context({'name': 'Stephane'}) >>> t.render(c) u'My name is Stephane.'
需要注意的是,t.render(c)返回值是一個Unicode對象,不是普通的字符串。 你可以通過字符串前的u來區分。 在Django框架中,會一直使用Unicode字符串對象而不是普通的字符串。
4.1.3. 字典和Contexts
Python的字典數據類型就是關鍵字和它們值的一個映射,Context 和字典很類似。context變量名必須由英文字符開始 (A-Z或a-z)並可以包含數字字符、下划線和小數點。
Context在Django里是 Context 類,她的構造函數帶有一個可選的參數: 一個字典映射變量和它們的值。 調用 Template 對象 的 render() 方法時,傳遞context來填充模板參數的值。
4.1.4. 同一模板,多個上下文
一旦有了 模板 對象,我們可以通過它渲染多個context來獲得不同的動態頁面效果, 例如:
>>> from django.template import Template, Context >>> t = Template('Hello, {{ name }}') >>> print t.render(Context({'name': 'John'})) Hello, John >>> print t.render(Context({'name': 'Julie'})) Hello, Julie >>> print t.render(Context({'name': 'Pat'})) Hello, Pat
4.2. 在視圖中使用模板
現在我們使用模板技術來創建視圖。 重新打開我們在前一章在 mysite.views 中創建的 current_datetime 視圖:
from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
依據用 Django 模板系統把該視圖修改為如下代碼:
from django.template import Template, Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = Template("<html><body>It is now {{ current_date }}.</body></html>") html = t.render(Context({'current_date': now})) return HttpResponse(html)
現在我們雖然使用了模板系統,但並未真正的實現數據與表現的分離,模板仍然嵌入在Python代碼里。 下面我們在改進一下代碼,將模板置於一個單獨的文件中,並在視圖中加載模板文件來最終解決表現與數據分開的問題。
4.3. 模板加載
Django 為我們提供了一種使用方便且功能強大的 API ,用於從磁盤中加載模板。要使用此模板加載API,首先我們需將模板的存放位置告訴框架,在settings.py中配置模板文件的保存路徑。打開mysite settings.py配置文件,找到TEMPLATE_DIRS設置項,加上文檔模板的保存路徑。
告訴 Django 加載模板時,在哪里查找模板。 選擇一個目錄用於存放模板並將其添加到 TEMPLATE_DIRS 中,本例子中我們在mysite目錄下創建子目錄templates來放置模板文件,配置TEMPLATE_DIRS可以使用絕對路徑來進行配置(即從文件系統根目錄開始的目錄路徑)。
TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. 'C:\My Files\Python Projects\mysite\templates', )
下面我們是使用Python 代碼這一點來構建動態的TEMPLATE_DIRS路勁的內容,代碼如下:
import os.path TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'), )
這段代碼使用了Python 內部變量 __file__ ,該變量被自動設置為settings.py 文件所在的目錄,然后由os.path.join 這個方法將這目錄與 templates 進行連接。在windows下,它會智能地選擇正確的后向斜杠”“進行連接,而不是前向斜杠”/”。
接下來修改視圖代碼,框架使用 Django 模板加載功能來返回 current_datetime 視圖:
from django.template.loader import get_template from django.template import Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = get_template('current_datetime.html') html = t.render(Context({'current_date': now})) return HttpResponse(html)
同時,在模板目錄中創建包括以下模板代碼 current_datetime.html 文件:
<html><body>It is now {{ current_date }}.</body></html>
這樣如下圖,是模板直接在IE中瀏覽的效果。
注意:模板的目錄結構,否則無法正常加載模板,mytime URL最后的訪問效果如下圖:
4.4.使用render_to_response()函數
我們已經告訴你如何載入一個模板文件,然后用 Context渲染它,最后返回這個處理好的HttpResponse對象給用戶。同時,Django提供了一個更方便簡單的函數,讓我們一次性地載入某個模板文件並渲染它,最后直接作為HttpResponse返回。
該快捷方式就是位於 django.shortcuts 模塊中名為 render_to_response() 的函數。下面代碼就是使用 render_to_response() 重新編寫過的 current_datetime 范例。
from django.shortcuts import render_to_response import datetime def current_datetime(request): now = datetime.datetime.now() return render_to_response('current_datetime.html', {'current_date': now})
render_to_response() 的第一個參數必須是要使用的模板名稱。第二個參數是為該模板創建 Context 時所使用的字典。
4.5. 小結
本章我們簡要闡述了Django動態網頁,以及如何通過加載模板文件來實現動態網頁。關於Django模板的語法規則,還支持包含、繼承等復雜的關系,進一步詳細的模板語法請大家參考Django開發手冊。
下一章我們將介紹Django是如何訪問數據庫的內容——模型。