了解前提:Django請求和響應設置
參考
在前提的演示中, HTML被直接硬編碼在 Python 代碼之中的用法只是為了方便演示。
但是實際生產(chǎn)中, 將頁面的設計和Python的代碼分離開會更干凈簡潔更容易維護。 我們可以使用 Django的 模板系統(tǒng) (Template System)來實現(xiàn)這種模式
—————————————————————————————————————
視圖
每個視圖必須要做的只有兩件事:返回一個包含被請求頁面內(nèi)容的 HttpResponse 對象,或者拋出一個異常,比如 Http404 。
視圖可以從數(shù)據(jù)庫里讀取記錄,可以使用一個模板引擎(比如 Django 自帶的,或者其他第三方的),可以生成一個 PDF 文件,可以輸出一個 XML,創(chuàng)建一個 ZIP 文件,你可以做任何你想做的事,使用任何你想用的 Python 庫。
—————————————————————————————————————
模板系統(tǒng)基本知識
項目的 TEMPLATES 配置項描述了 Django 如何載入和渲染模板。默認的設置文件設置了 DjangoTemplates 后端,并將 APP_DIRS 設置成了 True。這一選項將會讓 DjangoTemplates 在每個 INSTALLED_APPS 文件夾中尋找 "templates" 子目錄。
模板文件的路徑應該是 : [應用根目錄]/templates/[應用名]/[模板名].html
因為 Django 會尋找到對應的 app_directories ,所以你只需要使用 [應用名]/[模板名].html 就可以引用到這一模板了
一、模本概念和組成
模板是一個文本,用于分離文檔的表現(xiàn)形式和內(nèi)容。 模板定義了占位符以及各種用于規(guī)范文檔該如何顯示的各部分基本邏輯(模板標簽)。 模板通常用于產(chǎn)生HTML,但是Django的模板也能產(chǎn)生任何基于文本格式的文檔。
示例:
<html>
<head><title>Ordering notice</title></head>
<body>
<h1>Ordering notice</h1>
<p>Dear {{ person_name }},</p>
<p>Thanks for placing an order from {{ company }}. It's scheduled to
ship on {{ ship_date|date:"F j, Y" }}.</p>
<p>Here are the items you've ordered:</p>
<ul>
{% for item in item_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% if ordered_warranty %}
<p>Your warranty information will be included in the packaging.</p>
{% else %}
<p>You didn't order a warranty, so you're on your own when
the products inevitably stop working.</p>
{% endif %}
<p>Sincerely,<br />{{ company }}</p>
</body>
</html>
其中的格式含義
模板變量 :
用兩個大括號括起來的文字, 意味著在此處插入指定變量的值。
附:模板變量的解析順序
模板標簽 :
被大括號和百分號包圍的文本(例如 {% if ordered_warranty %} )是 模板標簽(template tag) 。標簽(tag)定義比較明確,即: 僅通知模板系統(tǒng)完成某些工作的標簽。
過濾器:
形如例子中: {{ship_date|date:”F j, Y” }}格式作為過濾器(filter), 我們將變量ship_date傳遞給date過濾器,同時指定參數(shù)”F j,Y”。date過濾器根據(jù)參數(shù)進行格式輸出。 過濾器是用管道符(|)來調(diào)用的。
二、模板結(jié)合視圖的使用
如果要額外了解模板作為python庫的獨立運行機制, 還有其中內(nèi)置標簽和模板的特殊行為,
參考: 模板系統(tǒng)獨立工作原理總結(jié)
由于目前普遍都是模本結(jié)合視圖一起呈現(xiàn), 以下主要總結(jié)結(jié)合使用的方法。
1、首先創(chuàng)建模板結(jié)構(gòu) [應用根目錄]/templates/[應用名]/[模板名].html
2、完善模板內(nèi)容, 設計模板交互規(guī)則
3、創(chuàng)建模板對應視圖, 將視圖的請求訪問注冊到urls.py文件
4、在視圖中使用template 庫的get_template獲取模板對象, 使用shortcuts 或template 庫的render渲染模板(基礎用法), 將復雜的數(shù)據(jù)或數(shù)據(jù)對象以字典的形式傳遞給模本系統(tǒng), 由后者進行深度變量的查找。
三、在模板中使用Http404方法拋出404, 以便django處理并顯示404頁面
使用情景, 當數(shù)據(jù)庫根據(jù)頁面交互數(shù)據(jù)查不到數(shù)據(jù), 需要手動扔出404, 但路由配置失敗或者訪問到錯誤路由是, django自動報404,
from django.shortcuts import render
from .models import Question
# ...
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})
上面這個流程主要是當數(shù)據(jù)庫根據(jù)頁面交互數(shù)據(jù)查不到數(shù)據(jù), 需要手動扔出404, 其實有一個快捷函數(shù)可以直接兩步操作一起進行get_object_or_404。
4、去除模板訪問的硬編碼
由于在模板中定義到api的訪問路由由urls.py文件定義, 而后者隨時可能會改變一節(jié)路由, 故路由在模板中不能進行硬編碼。
形如:
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
// polls是路由匹配字符
需要改成:
<li><a href="{% url 'GDweb:detail' question.id %}">{{ question.question_text }}</a></li>
其中GDweb:detail為命名空間為GDweb的urls.py文件中的參數(shù)name為detail的指定路由, 指定之后, 不管路由匹配規(guī)則怎么變, 路由名字不變就可精準匹配。
GDweb:detail代表命名空間為GDweb(對應應用)下的路由, 為了讓多應用下Django 知道{% url %}標簽到底對應哪一個應用的 URL,在urls.py文件中, 可以定義app_name變量指定命名空間。
—————————————————————————————————————
shortcuts 庫的一個快捷函數(shù): render()?
「載入模板,填充上下文,再返回由它生成的 HttpResponse 對象」是一個非常常用的操作流程。于是 Django 提供了一個快捷函數(shù),我們用它來重寫 index() 視圖:
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
基于數(shù)據(jù)庫查詢?yōu)榭?04拋出的快捷函數(shù): get_object_or_404()?
嘗試用 模型的get() 函數(shù)獲取一個對象,如果不存在就拋出 Http404 錯誤也是一個普遍的流程。Django 也提供了一個快捷函數(shù),下面是修改后的詳情 detail() 視圖代碼:
from django.shortcuts import get_object_or_404, render
from .models import Question
# ...
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
—————————————————————————————————————