續學習Rust標準庫中常用的trait,在開始今天的學習之前,先把前面已經學過的trait做一個簡單的復習:
我們已經學習了FromStr, Deref, DerefMut, From, Into, TryFrom, TryInto這7個標準庫中的trait,今天學習Default trait,使用Default trait可以為類型提供缺省值。
std::default::Default trait使用起來是十分簡單的,先看一下它的定義:
pub trait Default {
fn default() -> Self;
}
為類型實現Default trait有兩種方式:
例1:
#[derive(Default)] //無法編譯通過 enum不能derive Default
pub enum PayStatus {
Unpaid,
Paid,
}
例2:
#[derive(Debug)]
pub enum PayStatus {
Unpaid,
Paid,
}
// 為枚舉PayStatus手工實現
impl Default for PayStatus {
fn default() -> Self {
PayStatus::Unpaid
}
}
// Price的所有字段類型都實現了Default, 因此可以derive Default
#[derive(Default, Debug)]
pub struct Price {
original_price: f64,
discounted_price: f64,
}
// Order的所有字段類型都實現了Default,因此可以derive Default
#[derive(Default, Debug)]
pub struct Order {
id: i64,
pay_status: PayStatus,
price: Price,
}
當類型實現了Default trait之后,在初始化時,可以部分初始化,其余部分使用Default::default()初始化。
例3:
fn main() {
let order1 = Order::default();
let order2 = Order {
id: 100,
..Order::default()
};
println!("order1 = {:?}", order1);
println!("order2 = {:?}", order2);
}
顏色屬性被用來設置文字的顏色。
顏色是通過CSS最經常的指定:
一個網頁的文本顏色是指在主體內的選擇:
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=640, user-scalable=no">
<title>項目</title>
<style>
body {
color: blue;
}
h1 {
color: #00ff00;
}
h2 {
color: rgb(255, 0, 0);
}
</style>
</head>
<body>
<h2>hello world</h2>
<h1>welcome to CaoZhou</h1>
</body>
</html>
注:對于W3C標準的CSS:如果你定義了顏色屬性,你還必須定義背景色屬性。
文本排列屬性是用來設置文本的水平對齊方式。
文本可居中或對齊到左或右,兩端對齊。
當text-align設置為"justify",每一行被展開為寬度相等,左,右外邊距是對齊(如雜志和報紙)。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
h1 {
text-align: center;
}
p.date {
text-align: right;
}
p.main {
text-align: justify;
}
</style>
</head>
<body>
<p class="date">2015 年 3 月 14 號</p>
<p class="main"> 從前有個書生,和未婚妻約好在某年某月某日結婚。到那一天,未婚妻卻嫁給了別人。書生受此打擊, 一病不起。 這時,路過一游方僧人,從懷里摸出一面鏡子叫書生看。書生看到茫茫大海,一名遇害的女子一絲不掛地躺在海灘上。路過一人, 看一眼,搖搖頭,走了。又路過一人,將衣服脫下,給女尸蓋上,走了。再路過一人,過去,挖個坑,小心翼翼把尸體掩埋了。 僧人解釋道, 那具海灘上的女尸,就是你未婚妻的前世。你是第二個路過的人,曾給過他一件衣服。她今生和你相戀,只為還你一個情。但是她最終要報答一生一世的人,是最后那個把她掩埋的人,那人就是他現在的丈夫。書生大悟,病愈。
</p>
<p><b>注意:</b> 重置瀏覽器窗口大小查看 "justify" 是如何工作的。</p>
</body>
</html>
text-decoration 屬性用來設置或刪除文本的裝飾。
從設計的角度看 text-decoration屬性主要是用來刪除鏈接的下劃線:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.none {}
.del {
text-decoration: none;
}
</style>
</head>
<body>
<p>原來的樣子</p>
<a href="#" class="none">wwwwwwwwwwwwwwwwww</a>
<p>去掉下劃線</p>
<a href="#" class="del">wwwwwwwwwwwwwwwwwwwww</a>
</body>
</html>
也可以這樣裝飾文字:
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=640, user-scalable=no">
<title>項目</title>
<style>
h1 {
text-decoration: overline;
}
h2 {
text-decoration: line-through;
}
h3 {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>This is heading 1</h1>
<h2>This is heading 2</h2>
<h3>This is heading 3</h3>
</body>
</html>
注:不建議強調指出不是鏈接的文本,因為這常常混淆用戶。
text-transform文本轉換屬性是用來指定在一個文本中的大寫和小寫字母。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=640, user-scalable=no">
<title>項目</title>
<style>
p.uppercase {
text-transform: uppercase;
}
p.lowercase {
text-transform: lowercase;
}
p.capitalize {
text-transform: capitalize;
}
</style>
</head>
<body>
<p class="uppercase">This is some text.</p>
<p class="lowercase">This is some text.</p>
<p class="capitalize">This is some text.</p>
</body>
</html>
text-indent文本縮進屬性是用來指定文本的第一行的縮進。
p {text-indent:50px;}
增加或減少字符之間的空間。
<style>
h1 {
letter-spacing:2px;
}
h2 {
letter-spacing:-3px;
}
</style>
指定在一個段落中行之間的空間。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=640, user-scalable=no">
<title>項目</title>
<style>
p.small {
line-height: 70%;
}
p.big {
line-height: 200%;
}
</style>
</head>
<body>
<p>
This is a paragraph with a standard line-height.<br> This is a paragraph with a standard line-height.<br> The default line height in most browsers is about 110% to 120%.<br>
</p>
<p class="small">
This is a paragraph with a smaller line-height.<br> This is a paragraph with a smaller line-height.<br> This is a paragraph with a smaller line-height.<br> This is a paragraph with a smaller line-height.<br>
</p>
<p class="big">
This is a paragraph with a bigger line-height.<br> This is a paragraph with a bigger line-height.<br> This is a paragraph with a bigger line-height.<br> This is a paragraph with a bigger line-height.<br>
</p>
</body>
</html>
增加一個段落中的單詞之間的空白空間。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=640, user-scalable=no">
<title>項目</title>
<style type="text/css">
p {
word-spacing: 30px;
}
</style>
</head>
<body>
<p>
This is some text. This is some text.
</p>
</body>
</html>
設置文本的垂直對齊圖像。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=640, user-scalable=no">
<title>項目</title>
<style>
img{
width: 200px;
height: 100px;
}
img.top {
vertical-align: text-top;
}
img.bottom {
vertical-align: text-bottom;
}
</style>
</head>
<body>
<p>An <img src="img/logo.png" /> image with a default alignment.</p>
<p>An <img class="top" src="img/logo.png" /> image with a text-top alignment.</p>
<p>An <img class="bottom" src="img/logo.png" /> image with a text-bottom alignment.</p>
</body>
</html>
設置文本陰影。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=640, user-scalable=no">
<title>項目</title>
<style>
h1{
text-shadow: 2px 2px #FF0000;
}
</style>
</head>
<body>
<h1>Text-shadow effect</h1>
</body>
</html>
本文主要介紹了CSS文本樣式實際應用中應該如何去操作,通過講解文本中對應的屬性去改變文本的表現形式。使用豐富的效果圖的展示,能夠更直觀的看到運行的效果,能夠更好的理解。使用Html語言,代碼結構更佳的清晰,能夠幫助你更好的學習。
之前理解Django那篇文章中,我們學習了在Django中如何使用視圖。現在,這篇文章將學習如何使用Django模板。模板是在Django項目中構建用戶界面的主要工具。讓我們學習一下在視圖中如何使用模板,以及Django的模板系統能夠提供什么特性。
設置模板
我們需要一個地方放置模板。模板是靜態文件,Django會在里面填充數據。為了使用那些文件,我們必須告訴Django在哪里可以找到它們。
像Django的大多數組成部分一樣,這項配置在項目的配置文件里面。在你執行startproject命令之后,你可在配置文件中找到一個叫TEMPLATES的小節。這個小節的內容像這樣:
Django的模板系統可以使用多個模板后端。這個后端決定了模板如何運行。我推薦使用Django默認的模板語言。這個模板語言對Django這個框架有最緊密的集成和最好的支持。
下一個需要注意的地方是APP_DIRS的值是True。對于Django的模板語言,將這個值設置為True將使Django在每個應用項目的templates目錄中查找模板文件。注意這將包括任何第三方應用,所以最好保持這個值為True。
那模板應該放到哪里?在Django社區,不同開發者對此有不同想法。一些開發者認為應該將所有模板都放在所在應用中。另一部分開發者將項目的所有模板放到一個單獨的目錄。我就是這第二種開發者。我發現將項目的所有模板放到一個單獨的目錄是很有價值的。
在我看來,將模板保存在單個目錄中使系統中所有布局和UI位置非常清楚。如果我們在Django中想使用該模式,必須設置DIRS變量包含這個目錄。我建議在項目的根目錄中保留一個templates目錄。如果你這樣做,DIRS變量值將變成類似這樣:
最后,還有OPTIONS變量。每個后端都能接受各種選項。startproject設置了許多上下文處理器。我們將在后面文章中回到上文處理器的話題上來。
模板設置好之后,你就可以繼續往下進行了!
配合渲染器使用模板
Django通過渲染模板的方式來構建用戶界面。渲染的思想是通過動態數據結合靜態模板文件來產生最終的輸出。
為了生成包含渲染輸出的HttpResponse, 我們使用render函數。讓我們看一個例子,
在這個例子中,這個視圖將使用路徑為templates/hello.txt的模板,它的內容:
當這個視圖對一個請求進行應答時,用戶將在它的瀏覽器中看到“Hello Johnny”。關于這個例子,這里有一些有趣的事情需要注意:
這個模板可以是任何類型的純文本文件。我們常用HTML來創建用戶界面,因此我們常看到some_template.html,但是Django模板系統可以渲染任何類型的純文本文件。
在渲染的過程中,Django使用上下文數據字典并以它的關鍵字作為模板中的變量名。由于特殊的雙花括號語法,在上下文中模板的后端把{{ name }}替換為字面值“Johnny”。
使用模板的核心觀念是將上下文和靜態布局相融合。文章的剩余部分會基于此觀念,并會展示Django模板語言還能帶來什么。
看到TemplateView,你可能會回想起上一篇文章。在那些例子中,我們提供一個模板名字,然后我說到Django會處理剩下的事情。現在你開始理解Django獲取模板名字,然后調用類似render的代碼來生成一個HttpResponse。當時,那些例子缺少與模板結合起來的上下文數據。下面是一個完整的例子復現上述過程,代碼如下:
這個例子用 get_context_data, 因此我們能向渲染系統中插入我們的動態數據,來產生我們想要的應答。
在一個真實的應用中,我們需要專注寫大量的代碼來構建一個真正動態的上下文(context)。為了使模板系統的機制清晰,在這些例子中我使用的是靜態數據。當你看到所使用的上下文時,試著去想象使用更加復雜的數據來創建一個用戶界面。
以上這些是渲染的基礎。我們現在把我們的注意力轉向Django模板語言的能力。
模板實戰
當使用模板時,我們把上下文數據插入到模板里各個占位符的位置。
模板變量是使用上下文填充占位符最常見的形式。上節中我們展示了一個使用name變量的例子。上下文字典中包含一個name關鍵字,而雙花括號{{ name }}代表name值應該展示在哪里。
當上下文數據更加復雜時,我們也可以用點號獲取。例如像這樣的模板上下文:
Django模板不能使用常規的字典(例如{{ address['street'] }}
)獲取這個上下文數據。這時你應該用點號記法來獲取字典中的數據。
上面模板將渲染成:
Django模板同時努力適應不同類型的上下文數據。你也可以傳遞一個Python類的實例,比如和前面字典關鍵字一樣屬性的地址類。這時模板工作的效果是一樣的。
通過使用標簽的形式,核心模板語言提供了標準的編程邏輯關鍵字。模板標簽是這樣{% some_tag %},然而模板變量是這樣 {{ some_variable }}。變量代表用于填入值的占位符,但是標簽提供了更多的作用。
我們可以從兩個核心標簽開始學習,if 和 for。
標簽if用于模板需要處理條件判斷的時候。
這個例子只包含一個當用戶登錄到應用時歡迎信息的HTML頭部標簽。我們用if標簽開始這個例子。注意觀察if標簽結尾需要一個endif標簽。模板必須認真對待空格,因為布局依賴那些空格。模板語言不能像在Python中那樣用空格來表示范圍,所以需要用結束標簽。你可能猜到了,在if/endif標簽對中間也可以有else和elif標簽。
在這個例子中,只有一個頭部標簽根據用戶是否驗證來渲染。
for循環標簽是另一個核心標簽。在Django模板中,for循環會像你想象到的那樣工作。
Django會循環遍歷像列表一樣的可迭代對象,并對每個可迭代對象的中的項讓用戶輸出模板響應。如果上面的例子中列表的內容像下面一樣:
對應的輸出的大概會是這樣:
有時在for循環中的某個特定的元素上,你可能想采取一些特別的操作。在模板中不能直接使用Python內建的enumerate函數,但是在for標簽中有一個叫forloop的特別變量可用。這個forloop變量有一些你可用的屬性像first和last,讓模板對某個循環對象做不同的處理。
這個例子會這樣生成:
有了變量、if標簽以及for標簽,你可以制作一些相當強大的模板,但是除了這些還有更多東西可以發掘。
更多關于上下文的內容
在整個模板的設置項中,我們沒有詳細講解上下文處理器。上下文處理器是當模板被渲染時可以用來擴展上下文的有效方式。
這是一組當你用Django的startproject命令時默認生成的上下文處理器配置。
上下文處理器是接收HttpRequest,處理后返回字典的函數(嚴格來說是調用者,不過這里關注的是函數)。返回的字典和其他上下文一起傳遞給模板。
我們看看包含在上述列表中request的上下文處理器的實際定義。
這就是定義!因為有上下文處理器,這個request對象可以在你項目的任何模板中當作變量使用。這個功能非常強大。
工具條
不要害怕去看項目依賴的源代碼。記住你最喜歡的框架都是普通人寫的。你可以從他們寫的代碼中學到有價值的東西。這些代碼最開始可能看起來比較嚇人,但是這沒有捷徑可走。
上下文處理器的副作用是它們會對所有的請求都執行。如果你寫了一個做大量計算運行緩慢的上下文處理器,每個請求都會受到這個性能的影響。
所以,需要小心謹慎地使用上下文處理器。
可復用的模板代碼
現在讓我們說說模板系統的一個強大特性:可復用的代碼片段。
想象一個網站,大部分的頁面有相似的外觀和感覺。他們通過重復大量相同的HTML實現,HTML是一種定義頁面結構的超文本標記語言。這些頁面使用相同的CSS(層疊樣式表),層疊樣式表是定義頁面元素外觀形狀的樣式。
想象你被要求管理一個網站,并且你需要創建兩個獨立的頁面。主頁看起來像這樣:
并且在網站背后有一個介紹公司的頁面。
這些例子有少量的HTML,但是如果你被要求把styles.css樣式表改為設計師制作的叫做 better_styles.css新的
樣式表怎么辦?你需要在兩個頁面同時更新。現在想象你有2000個頁面而不是兩個頁面,在這樣一個網站快速地做大量修改幾乎不可能。
Django通過用幾個標簽幫助你完全避免這樣的情形。讓我們寫一個取名base.html的新模板。
我們通過block標簽創建了一個可復用的模板!我們可以修改我們的主頁使用這個新模板。
這個新版主頁擴展了這個基礎模板。所有模板需要做的是定義自己的用于填充內容的main語句塊。我們可以對介紹頁面做相同的操作。
如果我們現在重新接到將styles.css樣式表替換為better_styles.css樣式表的任務時, 我們可以在base.html中更新,然后將修改的內容應用到所有以它為基礎模板擴展的頁面。即使有2000個從base.html擴展的頁面, 改變樣式表時依然是一行代碼就可以改變整個站點。
這就是Django模板擴展系統的強大之處。
另一個復用的強大的工具是include的標簽。當你想在多個地方引用一部分模板代碼時include標簽非常有用。你想用include來實現:
保持模板整潔。你可以將一個大模板拆分成多個更好管理的小片段。
在你網站的不同部分用其中某一個模板片段。你可能有一個模板片段可能只會在幾個頁面用。
回到我們網站的例子,想象base.html代碼行數增長到20000行。找到模板中你想改變的部分現在變得更加困難。我們可以將模板分解成更小的片段。
這個include標簽可以將那些額外的模板片段包含到所在位置。給模板取一個好的名字,如果你需要像導航一樣改變一些章節的結構,你可以通過合適名字找到所需要的模板。
block, extends和include是保持用戶界面代碼避免在大量重復中無序擴展的核心標簽。
接下來,讓我們討論更多Django的內置模板標簽,這些標簽使你更加熟練掌控UI。
模板的工具箱
Django的文檔中包含大量可用于項目的內置標簽。我們的內容無法覆蓋所有這些標簽,但是我將關注幾個標簽給你展示哪些東西是可用的。
除了我們已經講過的標簽外,其中最常用的一個內置標簽就是url標簽。回憶那篇關于URLs的文章,通過reverse函數你可以將URL與一個命名視圖聯系起來。如果你想模板中用URL怎么辦?你可以這樣做:
盡管這樣可以運行,但是所有URL必須通過上下文路由是令人厭煩的。然而,我們的模板可以直接創建所需要的URL。下面才是a_template.html應該有的樣子。
這個url標簽是模板中與reverse函數作用一樣的東西。像它的reverse一樣,url可以接受args或者kwargs參數,這些是期望用于路由的其他變量。url是一個極其有用的工具并且是很可能在創建用戶界面中用很多次的標簽。
另一個有用的標簽是now標簽。now是一個用于展示當前時間相關信息方便的方法。用Django中的格式說明符,你可以告訴模板怎樣去展示當前時間。想在網站里添加當前的版權年份嗎?一點問題都沒有!
最后需要學習的內建標簽是spaceless標簽。HTML對空格部分敏感。有一些令人沮喪的情形,當你構建用戶界面時,空格敏感性帶來的后果會非常可怕。
當你用CSS的時候,在那些列表項前面縮進的空格(或者跟著它們的下一行字符)可能會給你帶來麻煩。意識到空格可能影響布局這個問題,我們可以像下面這樣使用spaceless標簽:
這個整潔的模板小標簽會移除所有HTML標簽中間的空格,所以效果是這樣的:
通過移除額外的空格,你在用CSS樣式表時獲得更多便利的體驗,并避免一些沮喪情緒。
這里還有另一種內建類型我們目前還沒有學習到。另一種內建函數叫做過濾器。過濾器改變你模板中變量的輸出。過濾器的語法有一點有趣。它看起來像這樣:
這里面重要的元素是緊跟在每個變量后面的管道符號。這個符號是在告訴模板系統我們想要對變量做一些轉換。需要注意的是過濾器用在雙花括號中,而不是像使用標簽那樣的{%語法。
一個非常常見的過濾器是date過濾器。當你在上下文中傳遞Python的時間實例,你可用date過濾器來控制時間的格式。date過濾器的文檔中演示了在修改時間格式時可用的選項有哪些。
如果a_datetime是一個4月愚人節的實例,然后它會返回像2020-04-01的字符串。date過濾器有許多格式說明符,你可生成所能想到的絕大多數日期輸出格式。
當模板變量的值計算為False時,default是一個有用的過濾器。當你獲取到一個變量為空字符串時,這是完美的。下面這個例子中如果變量是非真值,將會輸出“Nothing to see here”。
length是一個簡單的列表過濾器。{{ a_list_variable | length }} 將會計算出一個數字。它功能和Django模板中的len函數一樣。
我非常喜歡linebreaks過濾器。如果你創建一個表格(下一篇文章我們會學習到)并且有一個文本區域用戶可以輸入新行,如果當渲染用戶數據時你想顯示那些新行,linebreaks過濾器會非常有用。HTML默認不會顯示換行的字符。linebreaks過濾器會將\n轉換為一個<br> HTML標簽,這很方便!
在繼續往下學習之前,讓我們學習兩個標簽。
當文本需要計算東西的個數時候,pluralize是一個方便的標簽。下面是計算項目數的例子。
如果列表中有0、1 或者更多的項目,pluralize標簽將計算出正確的結果。
在我們學習的旅程中,最后一個是yesno標簽。yesno適合將True|False|None轉換成有意義的文本消息。想象我們創作一個應用追蹤各種事件,用戶注意力集中在三個值中的某一個。我們模板可能看起來像這樣。
依賴于user_accepted這個值,模板將會展示一些有用的信息給用戶。
還有很多Django的內建功能,挑選我最喜歡的功能是非常困難的。你可以查一下完整的列表,看看哪些可能會你有用。
如果Django內置功能沒有覆蓋你想要的功能怎么辦?不要怕,Django允許你為自己定制標簽和過濾器。接下來我們看看如何來實現。
構建你自己的模板武器
當你需要構建你自己的模板標簽或者過濾器時,Django給你提供了制作它們的工具。
這里有三個主要的元素用來定制標簽:
在Django期望的地方定義你自己的標簽。
在模板引擎中注冊標簽。
在模板中加載標簽,這樣它們可被用。
第一步是將標簽放到正確的位置。為此,在Django應用中我們需要一個名為templatetags的Python包。我們也需要一個模塊在那個目錄里。要小心謹慎地給模塊命名,因為它會在稍后加載到模板時用。
下一步,我們需要制作標簽或者過濾器并且注冊它。讓我們從過濾器的例子開始。
現在,如果我們有一個message變量,我們可以給它提供一些pizzazz。為了用這個定制的過濾器,我們必須用load標簽把我們的標簽模板加載到模板。
如果我們的消息是“You got a perfect score!”,然后模板會選擇三個選項之一,顯示在這條信息之后,比如“You got a perfect score! Wowza!”。
簡單的定制標簽的編寫和定制過濾器非常的相似。這里代碼比語言描述的更好。
我們可以加載這個定制標簽,并且像其他內建標簽一樣用我們標簽。
這個搞笑的歡迎標簽會處理多個輸入變量并且根據提供的級別進行變化。這個例子的中會顯示“Hello great champion He-Man!”。
在我們的例子中,僅僅學習了最常見的定制標簽。還有許多更加高級的定制標簽特性,你可以在Django定制模板標簽文檔探索。
總結
現在我們已經學習了模板的實戰!我們已經學習的以下內容:
如何設置你網站的模板
從視圖中調用模板的方法
如何使用數據
如何處理邏輯
可用于模板的內置標簽和過濾器
使用你自己的代碼擴展定制模板
英文原文:https://www.mattlayman.com/understand-django/templates-user-interfaces/
譯者:穆勝亮
*請認真填寫需求信息,我們會在24小時內與您取得聯系。