做者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!html
在以前的程序中,咱們直接生成一個字符串,做爲http回覆,返回給客戶端。這一過程當中使用了django.http.HttpResponse()。數據庫
在這樣的一種回覆生成過程當中,咱們實際上將數據和視圖的格式混合了到上面的字符串中。看似方便,卻爲咱們的管理帶來困難。想像一個成熟的網站,其顯示格式會有許多重複的地方。若是能夠把數據和視圖格式分離,就能夠重複使用同一視圖格式了。django
Django中自帶的模板系統,能夠將視圖格式分離出來,做爲模板使用。這樣,不但視圖能夠容易修改,程序也會顯得美觀大方。編程
「她是我心中最美的人」,姜戈對德國人說。post
咱們拿一個獨立的templay.html文件做爲模板。它放在templates/west/文件夾下。文件系統的結構如今是:網站
mysite/
├── mysite
├── templates
│ └── west
└── west
templay.html文件的內容是:url
<h1>{{ label }}</h1>
能夠看到,這個文件中,有一個奇怪的雙括號包起來的陌生人。這就是咱們將來數據要出現的地方。而相關的格式控制,即<h1>標籤,則已經標明在該模板文件中。spa
咱們須要向Django說明模板文件的搜索路徑,修改mysite/settings.py,添加:code
# Template dir
TEMPLATE_DIRS = ( os.path.join(BASE_DIR, 'templates/west/'), )
若是還有其它的路徑用於存放模板,能夠增長該元組中的元素,以便Django能夠找到須要的模板。htm
咱們如今修改west/views.py,增長一個新的對象,用於向模板提交數據:
# -*- coding: utf-8 -*-
#from django.http import HttpResponse
from django.shortcuts import render def templay(request): context = {} context['label'] = 'Hello World!'
return render(request, 'templay.html', context)
能夠看到,咱們這裏使用render來替代以前使用的HttpResponse。render還使用了一個詞典context做爲參數。這就是咱們的數據。
context中元素的鍵值爲'label',正對應剛纔的「陌生人」的名字。這樣,該context中的‘label’元素值,就會填上模板裏的坑,構成一個完整的http回覆。
做爲上節內容的一個小練習,自行修改west/urls.py,讓http://127.0.0.1:8000/west/templay的URL請求能夠找到相應的view對象。
訪問http://127.0.0.1:8000/west/templay,能夠看到頁面:
「我給你講個故事吧,勇士拯救公主的故事」,德國人說。
再來回顧一下整個流程。west/views.py中的templay()在返回時,將環境數據context傳遞給模板templay.html。Django根據context元素中的鍵值,將相應數據放入到模板中的對應位置,生成最終的http回覆。
這一模板系統能夠與Django的其它功能相互合做。上一回,咱們從數據庫中提取出了數據。若是將數據庫中的數據放入到context中,那麼就能夠將數據庫中的數據傳送到模板。
修改上次的west/views.py中的staff:
def staff(request): staff_list = Character.objects.all() staff_str = map(str, staff_list) context = {'label': ' '.join(staff_str)} return render(request, 'templay.html', context)
練習: 顯示上面的staff頁面。
「勇士翻太高山,並不是由於他不懼怕。」
Django實際上提供了豐富的模板語言,能夠在模板內部有限度的編程,從而更方便的編寫視圖和傳送數據。
咱們下面體驗一下最多見的循環與選擇。
上面的staff中的數據其實是一個數據容器,有三個元素。剛纔咱們將三個元素鏈接成一個字符串傳送。
實際上,利用模板語言,咱們能夠直接傳送數據容器自己,再循環顯示。修改staff()爲:
def staff(request): staff_list = Character.objects.all() return render(request, 'templay.html', {'staffs': staff_list})
從數據庫中查詢到的三個對象都在staff_list中。咱們直接將staff_list傳送給模板。
將模板templay.html修改成:
{% for item in staffs %} <p>{{ item.id }}, {{item}}</p> {% endfor %}
咱們以相似於Python中for循環的方式來定義模板中的for,以顯示staffs中的每一個元素。
還能夠看到,對象.屬性名的引用方式能夠直接用於模板中。
選擇結構也與Python相似。根據傳送來的數據是否爲True,Django選擇是否顯示。使用方式以下:
{% if condition1 %}
... display 1
{% elif condiiton2 %}
... display 2
{% else %}
... display 3
{% endif %}
其中的elif和else和Python中同樣,是能夠省略的。
「勇士屠殺惡龍,並不是由於他不恐懼。」
模板能夠用繼承的方式來實現複用。咱們下面用templay.html來繼承base.html。這樣,咱們可使用base.html的主體,只替換掉特定的部分。
新建templates/west/base.html:
<html>
<head>
<title>templay</title>
</head>
<body>
<h1>come from base.html</h1> {% block mainbody %} <p>original</p> {% endblock %} </body>
</html>
該頁面中,名爲mainbody的block標籤是能夠被繼承者們替換掉的部分。
咱們在下面的templay.html中繼承base.html,並替換特定block:
{% extends "base.html" %} {% block mainbody %} {% for item in staffs %} <p>{{ item.id }},{{ item.name }}</p> {% endfor %} {% endblock %}
第一句說明templay.html繼承自base.html。能夠看到,這裏相同名字的block標籤用以替換base.html的相應block。
「勇士穿過地獄火焰,由於,她值得。」
使用模板實現視圖分離。
數據傳遞,模板變量,模板循環與選擇,模板繼承。
姜戈靜靜的說,「我懂得他的感覺。」
歡迎閱讀「被解放的姜戈」系列文章。