Django用戶界面模板

Django用戶界面模板

在之前理解Django那篇文章中,我們學習了在Django中如何使用視圖。現在,這篇文章將學習如何使用Django模板。模板是在Django項目中構建用戶界面的主要工具。讓我們學習一下在視圖中如何使用模板,以及Django的模板系統能夠提供什麼特性。

設置模板

我們需要一個地方放置模板。模板是靜態文件,Django會在裡面填充數據。為了使用那些文件,我們必須告訴Django在哪裡可以找到它們。

像Django的大多數組成部分一樣,這項配置在項目的配置文件裡面。在你執行startproject命令之後,你可在配置文件中找到一個叫TEMPLATES的小節。這個小節的內容像這樣:

Django用戶界面模板

Django的模板系統可以使用多個模板後端。這個後端決定了模板如何運行。我推薦使用Django默認的模板語言。這個模板語言對Django這個框架有最緊密的集成和最好的支持。

下一個需要注意的地方是APP_DIRS的值是True。對於Django的模板語言,將這個值設置為True將使Django在每個應用項目的templates目錄中查找模板文件。注意這將包括任何第三方應用,所以最好保持這個值為True。

那模板應該放到哪裡?在Django社區,不同開發者對此有不同想法。一些開發者認為應該將所有模板都放在所在應用中。另一部分開發者將項目的所有模板放到一個單獨的目錄。我就是這第二種開發者。我發現將項目的所有模板放到一個單獨的目錄是很有價值的。

在我看來,將模板保存在單個目錄中使系統中所有佈局和UI位置非常清楚。如果我們在Django中想使用該模式,必須設置DIRS變量包含這個目錄。我建議在項目的根目錄中保留一個templates目錄。如果你這樣做,DIRS變量值將變成類似這樣:

Django用戶界面模板

最後,還有OPTIONS變量。每個後端都能接受各種選項。startproject設置了許多上下文處理器。我們將在後面文章中回到上文處理器的話題上來。

模板設置好之後,你就可以繼續往下進行了!

配合渲染器使用模板

Django通過渲染模板的方式來構建用戶界面。渲染的思想是通過動態數據結合靜態模板文件來產生最終的輸出。

為了生成包含渲染輸出的HttpResponse, 我們使用render函數。讓我們看一個例子,

Django用戶界面模板

在這個例子中,這個視圖將使用路徑為templates/hello.txt的模板,它的內容:

Django用戶界面模板

當這個視圖對一個請求進行應答時,用戶將在它的瀏覽器中看到“Hello Johnny”。關於這個例子,這裡有一些有趣的事情需要注意:

  1. 這個模板可以是任何類型的純文本文件。我們常用HTML來創建用戶界面,因此我們常看到some_template.html,但是Django模板系統可以渲染任何類型的純文本文件。

  2. 在渲染的過程中,Django使用上下文數據字典並以它的關鍵字作為模板中的變量名。由於特殊的雙花括號語法,在上下文中模板的後端把{{ name }}替換為字面值“Johnny”。

使用模板的核心觀念是將上下文和靜態佈局相融合。文章的剩餘部分會基於此觀念,並會展示Django模板語言還能帶來什麼。

看到TemplateView,你可能會回想起上一篇文章。在那些例子中,我們提供一個模板名字,然後我說到Django會處理剩下的事情。現在你開始理解Django獲取模板名字,然後調用類似render的代碼來生成一個HttpResponse。當時,那些例子缺少與模板結合起來的上下文數據。下面是一個完整的例子復現上述過程,代碼如下:

Django用戶界面模板

這個例子用 get_context_data, 因此我們能向渲染系統中插入我們的動態數據,來產生我們想要的應答。

在一個真實的應用中,我們需要專注寫大量的代碼來構建一個真正動態的上下文(context)。為了使模板系統的機制清晰,在這些例子中我使用的是靜態數據。當你看到所使用的上下文時,試著去想象使用更加複雜的數據來創建一個用戶界面。

以上這些是渲染的基礎。我們現在把我們的注意力轉向Django模板語言的能力。

模板實戰

當使用模板時,我們把上下文數據插入到模板裡各個佔位符的位置。

模板變量是使用上下文填充佔位符最常見的形式。上節中我們展示了一個使用name變量的例子。上下文字典中包含一個name關鍵字,而雙花括號{{ name }}代表name值應該展示在哪裡。

當上下文數據更加複雜時,我們也可以用點號獲取。例如像這樣的模板上下文:

Django用戶界面模板

Django模板不能使用常規的字典(例如<code>{{ address['street'] }}/<code>)獲取這個上下文數據。這時你應該用點號記法來獲取字典中的數據。

Django用戶界面模板

上面模板將渲染成:

Django用戶界面模板

Django模板同時努力適應不同類型的上下文數據。你也可以傳遞一個Python類的實例,比如和前面字典關鍵字一樣屬性的地址類。這時模板工作的效果是一樣的。

通過使用標籤的形式,核心模板語言提供了標準的編程邏輯關鍵字。模板標籤是這樣{% some_tag %},然而模板變量是這樣 {{ some_variable }}。變量代表用於填入值的佔位符,但是標籤提供了更多的作用。

我們可以從兩個核心標籤開始學習,if 和 for。

標籤if用於模板需要處理條件判斷的時候。

Django用戶界面模板

這個例子只包含一個當用戶登錄到應用時歡迎信息的HTML頭部標籤。我們用if標籤開始這個例子。注意觀察if標籤結尾需要一個endif標籤。模板必須認真對待空格,因為佈局依賴那些空格。模板語言不能像在Python中那樣用空格來表示範圍,所以需要用結束標籤。你可能猜到了,在if/endif標籤對中間也可以有else和elif標籤。

Django用戶界面模板

在這個例子中,只有一個頭部標籤根據用戶是否驗證來渲染。

for循環標籤是另一個核心標籤。在Django模板中,for循環會像你想象到的那樣工作。

Django用戶界面模板

Django會循環遍歷像列表一樣的可迭代對象,並對每個可迭代對象的中的項讓用戶輸出模板響應。如果上面的例子中列表的內容像下面一樣:

Django用戶界面模板

對應的輸出的大概會是這樣:

Django用戶界面模板

有時在for循環中的某個特定的元素上,你可能想採取一些特別的操作。在模板中不能直接使用Python內建的enumerate函數,但是在for標籤中有一個叫forloop的特別變量可用。這個forloop變量有一些你可用的屬性像first和last,讓模板對某個循環對象做不同的處理。

Django用戶界面模板

這個例子會這樣生成:

Django用戶界面模板

有了變量、if標籤以及for標籤,你可以製作一些相當強大的模板,但是除了這些還有更多東西可以發掘。

更多關於上下文的內容

在整個模板的設置項中,我們沒有詳細講解上下文處理器。上下文處理器是當模板被渲染時可以用來擴展上下文的有效方式。

這是一組當你用Django的startproject命令時默認生成的上下文處理器配置。

Django用戶界面模板

上下文處理器是接收HttpRequest,處理後返回字典的函數(嚴格來說是調用者,不過這裡關注的是函數)。返回的字典和其他上下文一起傳遞給模板。

我們看看包含在上述列表中request的上下文處理器的實際定義。

Django用戶界面模板

這就是定義!因為有上下文處理器,這個request對象可以在你項目的任何模板中當作變量使用。這個功能非常強大。

工具條

不要害怕去看項目依賴的源代碼。記住你最喜歡的框架都是普通人寫的。你可以從他們寫的代碼中學到有價值的東西。這些代碼最開始可能看起來比較嚇人,但是這沒有捷徑可走。

上下文處理器的副作用是它們會對所有的請求都執行。如果你寫了一個做大量計算運行緩慢的上下文處理器,每個請求都會受到這個性能的影響。

所以,需要小心謹慎地使用上下文處理器。

可複用的模板代碼

現在讓我們說說模板系統的一個強大特性:可複用的代碼片段。

想象一個網站,大部分的頁面有相似的外觀和感覺。他們通過重複大量相同的HTML實現,HTML是一種定義頁面結構的超文本標記語言。這些頁面使用相同的CSS(層疊樣式表),層疊樣式表是定義頁面元素外觀形狀的樣式。

想象你被要求管理一個網站,並且你需要創建兩個獨立的頁面。主頁看起來像這樣:

Django用戶界面模板

並且在網站背後有一個介紹公司的頁面。

Django用戶界面模板

這些例子有少量的HTML,但是如果你被要求把styles.css樣式表改為設計師製作的叫做 <code>better_styles.css新的/<code>樣式表怎麼辦?你需要在兩個頁面同時更新。現在想象你有2000個頁面而不是兩個頁面,在這樣一個網站快速地做大量修改幾乎不可能。

Django通過用幾個標籤幫助你完全避免這樣的情形。讓我們寫一個取名base.html的新模板。

Django用戶界面模板

我們通過block標籤創建了一個可複用的模板!我們可以修改我們的主頁使用這個新模板。

Django用戶界面模板

這個新版主頁擴展了這個基礎模板。所有模板需要做的是定義自己的用於填充內容的main語句塊。我們可以對介紹頁面做相同的操作。

如果我們現在重新接到將styles.css樣式表替換為better_styles.css樣式表的任務時, 我們可以在base.html中更新,然後將修改的內容應用到所有以它為基礎模板擴展的頁面。即使有2000個從base.html擴展的頁面, 改變樣式表時依然是一行代碼就可以改變整個站點。

這就是Django模板擴展系統的強大之處。

另一個複用的強大的工具是include的標籤。當你想在多個地方引用一部分模板代碼時include標籤非常有用。你想用include來實現:

  1. 保持模板整潔。你可以將一個大模板拆分成多個更好管理的小片段。

  2. 在你網站的不同部分用其中某一個模板片段。你可能有一個模板片段可能只會在幾個頁面用。

回到我們網站的例子,想象base.html代碼行數增長到20000行。找到模板中你想改變的部分現在變得更加困難。我們可以將模板分解成更小的片段。

Django用戶界面模板

這個include標籤可以將那些額外的模板片段包含到所在位置。給模板取一個好的名字,如果你需要像導航一樣改變一些章節的結構,你可以通過合適名字找到所需要的模板。

block, extends和include是保持用戶界面代碼避免在大量重複中無序擴展的核心標籤。

接下來,讓我們討論更多Django的內置模板標籤,這些標籤使你更加熟練掌控UI。

模板的工具箱

Django的文檔中包含大量可用於項目的內置標籤。我們的內容無法覆蓋所有這些標籤,但是我將關注幾個標籤給你展示哪些東西是可用的。

除了我們已經講過的標籤外,其中最常用的一個內置標籤就是url標籤。回憶那篇關於URLs的文章,通過reverse函數你可以將URL與一個命名視圖聯繫起來。如果你想模板中用URL怎麼辦?你可以這樣做:

Django用戶界面模板

儘管這樣可以運行,但是所有URL必須通過上下文路由是令人厭煩的。然而,我們的模板可以直接創建所需要的URL。下面才是a_template.html應該有的樣子。

Django用戶界面模板

這個url標籤是模板中與reverse函數作用一樣的東西。像它的reverse一樣,url可以接受args或者kwargs參數,這些是期望用於路由的其他變量。url是一個極其有用的工具並且是很可能在創建用戶界面中用很多次的標籤。

另一個有用的標籤是now標籤。now是一個用於展示當前時間相關信息方便的方法。用Django中的格式說明符,你可以告訴模板怎樣去展示當前時間。想在網站裡添加當前的版權年份嗎?一點問題都沒有!

Django用戶界面模板

最後需要學習的內建標籤是spaceless標籤。HTML對空格部分敏感。有一些令人沮喪的情形,當你構建用戶界面時,空格敏感性帶來的後果會非常可怕。

Django用戶界面模板

當你用CSS的時候,在那些列表項前面縮進的空格(或者跟著它們的下一行字符)可能會給你帶來麻煩。意識到空格可能影響佈局這個問題,我們可以像下面這樣使用spaceless標籤:

Django用戶界面模板

這個整潔的模板小標籤會移除所有HTML標籤中間的空格,所以效果是這樣的:

Django用戶界面模板

通過移除額外的空格,你在用CSS樣式表時獲得更多便利的體驗,並避免一些沮喪情緒。

這裡還有另一種內建類型我們目前還沒有學習到。另一種內建函數叫做過濾器。過濾器改變你模板中變量的輸出。過濾器的語法有一點有趣。它看起來像這樣:

Django用戶界面模板

這裡面重要的元素是緊跟在每個變量後面的管道符號。這個符號是在告訴模板系統我們想要對變量做一些轉換。需要注意的是過濾器用在雙花括號中,而不是像使用標籤那樣的{%語法。

一個非常常見的過濾器是date過濾器。當你在上下文中傳遞Python的時間實例,你可用date過濾器來控制時間的格式。date過濾器的文檔中演示了在修改時間格式時可用的選項有哪些。

Django用戶界面模板

如果a_datetime是一個4月愚人節的實例,然後它會返回像2020-04-01的字符串。date過濾器有許多格式說明符,你可生成所能想到的絕大多數日期輸出格式。

當模板變量的值計算為False時,default是一個有用的過濾器。當你獲取到一個變量為空字符串時,這是完美的。下面這個例子中如果變量是非真值,將會輸出“Nothing to see here”。

Django用戶界面模板

length是一個簡單的列表過濾器。{{ a_list_variable | length }} 將會計算出一個數字。它功能和Django模板中的len函數一樣。

我非常喜歡linebreaks過濾器。如果你創建一個表格(下一篇文章我們會學習到)並且有一個文本區域用戶可以輸入新行,如果當渲染用戶數據時你想顯示那些新行,linebreaks過濾器會非常有用。HTML默認不會顯示換行的字符。linebreaks過濾器會將\n轉換為一個


HTML標籤,這很方便!

在繼續往下學習之前,讓我們學習兩個標籤。

當文本需要計算東西的個數時候,pluralize是一個方便的標籤。下面是計算項目數的例子。

Django用戶界面模板

如果列表中有0、1 或者更多的項目,pluralize標籤將計算出正確的結果。

Django用戶界面模板

在我們學習的旅程中,最後一個是yesno標籤。yesno適合將True|False|None轉換成有意義的文本消息。想象我們創作一個應用追蹤各種事件,用戶注意力集中在三個值中的某一個。我們模板可能看起來像這樣。

Django用戶界面模板

依賴於user_accepted這個值,模板將會展示一些有用的信息給用戶。

還有很多Django的內建功能,挑選我最喜歡的功能是非常困難的。你可以查一下完整的列表,看看哪些可能會你有用。

如果Django內置功能沒有覆蓋你想要的功能怎麼辦?不要怕,Django允許你為自己定製標籤和過濾器。接下來我們看看如何來實現。

構建你自己的模板武器

當你需要構建你自己的模板標籤或者過濾器時,Django給你提供了製作它們的工具。

這裡有三個主要的元素用來定製標籤:

  1. 在Django期望的地方定義你自己的標籤。

  2. 在模板引擎中註冊標籤。

  3. 在模板中加載標籤,這樣它們可被用。

第一步是將標籤放到正確的位置。為此,在Django應用中我們需要一個名為templatetags的Python包。我們也需要一個模塊在那個目錄裡。要小心謹慎地給模塊命名,因為它會在稍後加載到模板時用。

Django用戶界面模板

下一步,我們需要製作標籤或者過濾器並且註冊它。讓我們從過濾器的例子開始。

Django用戶界面模板

現在,如果我們有一個message變量,我們可以給它提供一些pizzazz。為了用這個定製的過濾器,我們必須用load標籤把我們的標籤模板加載到模板。

Django用戶界面模板

如果我們的消息是“You got a perfect score!”,然後模板會選擇三個選項之一,顯示在這條信息之後,比如“You got a perfect score! Wowza!”。

簡單的定製標籤的編寫和定製過濾器非常的相似。這裡代碼比語言描述的更好。

Django用戶界面模板

我們可以加載這個定製標籤,並且像其他內建標籤一樣用我們標籤。

Django用戶界面模板

這個搞笑的歡迎標籤會處理多個輸入變量並且根據提供的級別進行變化。這個例子的中會顯示“Hello great champion He-Man!”。

在我們的例子中,僅僅學習了最常見的定製標籤。還有許多更加高級的定製標籤特性,你可以在Django定製模板標籤文檔探索。

總結

現在我們已經學習了模板的實戰!我們已經學習的以下內容:

  • 如何設置你網站的模板

  • 從視圖中調用模板的方法

  • 如何使用數據

  • 如何處理邏輯

  • 可用於模板的內置標籤和過濾器

  • 使用你自己的代碼擴展定製模板

英文原文:https://www.mattlayman.com/understand-django/templates-user-interfaces/
譯者:穆勝亮Django用戶界面模板


分享到:


相關文章: