Python 領(lǐng)域運(yùn)用:Web 開發(fā)
1. Web 開發(fā)簡介
1.1 Web 的歷史
1989年,TimBerner 提出了一種能讓遠(yuǎn)隔兩地的研究者們共享知識的設(shè)想。它的基本理念是:借助多文檔之間相互關(guān)聯(lián)形成的超文本(HyperText),連成可相互參閱的 WWW(World Wide Web)。
在互聯(lián)網(wǎng)早期,網(wǎng)站的內(nèi)容是靜態(tài)的,瀏覽相同地址的頁面返回的內(nèi)容不會發(fā)生變化。由于網(wǎng)頁的內(nèi)容是不發(fā)生變化的,因此早期互聯(lián)網(wǎng)站只能用于共享靜態(tài)的文檔,無法實現(xiàn)復(fù)雜的應(yīng)用。
互聯(lián)網(wǎng)得到了飛速的發(fā)展,人們不再滿足網(wǎng)頁只有靜態(tài)文本的形式,出現(xiàn)了動態(tài)網(wǎng)頁的技術(shù),例如專用于開發(fā)動態(tài)網(wǎng)頁的 PHP 編程語言。1995 年,Rasmus Lerdorf 發(fā)明了 PHP 編程語言。PHP 是在服務(wù)器端執(zhí)行腳本語言,它動態(tài)生成 HTML 文本返回給瀏覽器。
1.2 出現(xiàn)了專門的 Web 開發(fā)工程師
在互聯(lián)網(wǎng)早期,網(wǎng)站中的主要內(nèi)容由靜態(tài)頁面構(gòu)成,開發(fā)一個網(wǎng)站并不需要太多的編程工作,網(wǎng)站開發(fā)人員會編寫 HTML 文件即可,很多網(wǎng)站甚至于不需要程序員的參與。
隨著互聯(lián)網(wǎng)的發(fā)展,網(wǎng)站的功能越來越復(fù)雜,網(wǎng)站提供的功能日趨豐富,網(wǎng)站更像是一個本地應(yīng)用程序,而不是單純展示內(nèi)容的網(wǎng)頁。在這個時期,開發(fā) Web 需要編寫大量的程序,一個復(fù)雜的 Web 開發(fā)項目包含有數(shù)萬行、甚至于數(shù)十萬行的源代碼。
隨著網(wǎng)站開發(fā)的需求的增加,出現(xiàn)了專門的 Web 開發(fā)工程師,在計算機(jī)行業(yè)的招聘網(wǎng)站上搜索 "Web 開發(fā)”,可以獲得大量的職位招聘信息:
2. Web 開發(fā)入門
本節(jié)介紹進(jìn)行 Web 開發(fā)所需要了解和掌握的技術(shù)。
2.1 HTML 基礎(chǔ)
HTML稱為超文本標(biāo)記語言,是一種標(biāo)識性的語言。它包括一系列標(biāo)簽.通過這些標(biāo)簽可以將網(wǎng)絡(luò)上的文檔格式統(tǒng)一,使分散的Internet資源連接為一個邏輯整體。HTML文本是由HTML命令組成的描述性文本,HTML命令可以說明文字,圖形、動畫、聲音、表格、鏈接等
HTML 不是一門編程語言,而是一種用于定義內(nèi)容結(jié)構(gòu)的標(biāo)記語言。HTML 由一系列的元素(elements)組成,這些元素可以用來包圍不同部分的內(nèi)容,使其以某種方式呈現(xiàn)或者工作。 一對標(biāo)簽( tags)可以為一段文字或者一張圖片添加超鏈接,將文字設(shè)置為斜體,改變字號,等等。
學(xué)習(xí) HTML 需要學(xué)習(xí)各種標(biāo)簽,例如使用 table 標(biāo)簽描述了一個 2 行 2 列的表格:
<table>
<tr>
<td>第 1 行 第 1 列</td>
<td>第 1 行 第 2 列</td>
</tr>
<tr>
<td>第 2 行 第 1 列</td>
<td>第 2 行 第 2 列</td>
</tr>
</table>
- table 標(biāo)簽描述了一個表格
- tr 標(biāo)簽描述表格中的一行
- td 標(biāo)簽描述表格中的一個單元
第 1 行 第 1 列 | 第 1 行 第 2 列 |
第 2 行 第 1 列 | 第 2 行 第 2 列 |
2.2 CSS 基礎(chǔ)
層疊樣式表 (CSS) 是用來添加樣式到你網(wǎng)站的代碼。舉例來說,你想讓文字是黑色還是紅色的?在屏幕的何處展示內(nèi)容?用什么背景圖像和顏色來裝飾你的網(wǎng)站?
和 HTML 類似,CSS 也不是真正的編程語言,甚至不是標(biāo)記語言。它是一門樣式表語言,這也就是說人們可以用它來選擇性地為 HTML 元素添加樣式。舉例來說,要選擇一個 HTML 頁面里所有的段落元素,然后將其中的文本改成紅色,可以這樣寫 CSS:
p {
color: red
}
2.3 Javascript 基礎(chǔ)
JavaScript(縮寫:JS)是一門完備的 動態(tài)編程語言。當(dāng)應(yīng)用于 HTML 文檔時,可為網(wǎng)站提供動態(tài)交互特性。例如:檢查輸入的合法性、在按下按鈕或收到表單數(shù)據(jù)時做出的響應(yīng)等。
JavaScript 的應(yīng)用場合極其廣泛,簡單到響應(yīng)按鈕點(diǎn)擊,復(fù)雜到游戲、2D/3D 動畫、大型數(shù)據(jù)庫驅(qū)動程序等等。
瀏覽器內(nèi)置的 Javascript API 提供了豐富的功能,比如:動態(tài)創(chuàng)建 HTML 和設(shè)置 CSS 樣式、生成2D 圖像與音頻樣本等。
2.4 使用 Python 作為 Web 后端
使用瀏覽器訪問網(wǎng)站的過程如下所示:
- 瀏覽器向網(wǎng)站發(fā)出請求
- 網(wǎng)站收到請求后,返回 HTML 文本作為響應(yīng)內(nèi)容
在下圖的例子中,服務(wù)器返回當(dāng)前時間 (HTML 的格式)。使用瀏覽器訪問網(wǎng)站時,顯示的內(nèi)容是動態(tài)的,每次都是當(dāng)前時間,如下所示:
在這個例子中,瀏覽器又被稱為前端,服務(wù)器又被稱為后端。后端收到請求后,做如下的工作:
- 分析用戶請求,獲取請求的參數(shù)
- 根據(jù)請求的參數(shù)進(jìn)行處理,可能會讀取數(shù)據(jù)庫
- 最終生成一段 HTML 文本返回給前端
Python 作為一個通用的編程語言,能夠完成以上的工作,由于其開發(fā)效率高,在 Web 后端開發(fā)中占有重要的一席之地。以下是慕課網(wǎng)的課程分類目錄,在后端開發(fā)的分類中,Python 和 Django (Python 的 web 框架) 占有兩個條目:
3. Web 開發(fā)框架
3.1 簡介
在傳統(tǒng)的軟件開發(fā)中,框架是一種提供了可重用的公共結(jié)構(gòu)的技術(shù),為構(gòu)建新的應(yīng)用程序提供了極大的便利??蚣苁且环N非常成熟的技術(shù),在多個領(lǐng)域得到了成功的應(yīng)用,例如:在桌面應(yīng)用程序開發(fā)的領(lǐng)域,微軟公司的 Visual Studio C++ 為應(yīng)用程序生成框架,基于 VC++ 應(yīng)用程序框架可以大大的提升桌面程序的開發(fā)效率。
隨著 Web 開發(fā)項目的復(fù)雜度的日益提升,軟件開發(fā)中的框架技術(shù)被引入到 Web 開發(fā)領(lǐng)域。Web 開發(fā)框架是用于進(jìn)行 web 開發(fā)的一套軟件架構(gòu),Web 框架為 Web 應(yīng)用程序提供了基礎(chǔ)的功能。開發(fā)人員在 Web 框架的基礎(chǔ)上實現(xiàn)自己的業(yè)務(wù)邏輯,基于 Web 框架開發(fā)應(yīng)用,開發(fā)人員只需要專注應(yīng)用的業(yè)務(wù)邏輯,非業(yè)務(wù)邏輯的基礎(chǔ)功能則由框架提供,從而提升開發(fā)效率。
3.2 常見的 Web 框架
目前,最流行的 Python 的 Web 開發(fā)框架是 Flask 框架和 Django 框架,截至 2019 年 9 月 2 日,F(xiàn)lask 在 Github 上的星數(shù)是 46179 顆,Django 的 Github 星數(shù)是 43806 顆,兩者幾乎難分伯仲,其它 Python Web 框架與 Flask 和 Django 星數(shù)相差甚遠(yuǎn)。
兩者的主要區(qū)別在于:Django 功能大而全,F(xiàn)lask 只包含基本的功能。
Django 采用一站式解決的思路,Django 集成有模板、表單、路由、認(rèn)證、基本的數(shù)據(jù)庫管理等內(nèi)建功能,開發(fā)者不用在選擇應(yīng)用的基礎(chǔ)設(shè)施上花費(fèi)大量時間。
Django 就像是一個裝潢好的房子(如下圖所示),它提供了各種家具,直接入住即可。
Flask 相對于 Django 而言是輕量級的 Web 框架。和 Django 不同,F(xiàn)lask 只提供了最核心的功能,輕巧、簡潔,通過定制第三方擴(kuò)展來實現(xiàn)具體功能。
默認(rèn)情況下,不包含數(shù)據(jù)庫抽象、用戶認(rèn)證、表單驗證、發(fā)送郵件等其它 Web 框架經(jīng)常包含的功能。Flask依賴用各種靈活的擴(kuò)展(比如郵件Flask Mail,用戶認(rèn)證Flask Login,數(shù)據(jù)庫Flask SQLAlchemy)來給Web應(yīng)用添加額外功能。
Flask 就像是一個沒有裝潢的房子(如下圖所示),用戶需要自己選擇各種家具才可以入住。
4. Web 框架提供的核心功能
4.1 路由配置
在 Web 開發(fā)過程中,經(jīng)常會遇到 “路由” 的概念。簡單來說,路由就是 URL 到處理函數(shù)的映射。
Web 后端處理大致流程可以看成這樣:
- 瀏覽器發(fā)出請求
- 服務(wù)器端監(jiān)聽到 80 端口的請求,解析請求的 url 路徑
- 根據(jù)服務(wù)器的路由配置,找到對應(yīng) url 對應(yīng)的處理函數(shù)
- 運(yùn)行處理函數(shù)生成一段 HTML 文本,并返回給瀏覽器
假設(shè)一個論壇系統(tǒng)由如下數(shù)據(jù)構(gòu)成:
- 主題,每個主題包含有標(biāo)題和內(nèi)容,使用 topicID 標(biāo)識該主題
- 用戶,每個用戶包含姓名和密碼,使用 userID 標(biāo)識該用戶
論壇的域名是 www.bbs.com,它向外界提供了若干可訪問的 URL:
URL | 功能 |
---|---|
http://www.bbs.com/topics/12373 | 訪問 topicID 為 12373 的主題 |
http://www.bbs.com/users/1353 | 訪問 userID 為 1353 的用戶頁面 |
在服務(wù)器端有兩個處理頁面函數(shù):
- showTopic(topicId) 顯示指定 topicId 的主題內(nèi)容
- showUser(userId) 顯示指定 userId 的用戶信息
在下圖中,當(dāng)用戶請求形式為 /topics/xxx 的 URL 時,服務(wù)器需要找到 showTopic 函數(shù)處理該請求;當(dāng)用戶請求形式為 /users/xxx 的 URL 時,服務(wù)器需要找到 showUser 函數(shù)處理該請求。

URL 到處理函數(shù)的映射,就被稱為路由。Web 開發(fā)框架提供了路由配置的功能,可以方便的指定處理 URL 的函數(shù)。
4.2 模板渲染
用 Python 生成 HTML 的過程十分繁瑣,需要進(jìn)行字符串拼接,代碼的可讀性差。假設(shè),在一個學(xué)生管理系統(tǒng)中,有一個頁面是展示所有學(xué)生的姓名、學(xué)號等信息,Python 后端程序通過讀取數(shù)據(jù)庫生成一段 HTML 文本,代碼如下:
def generateHtml():
html = ''
html += '<table>'
sql = 'SELECT * FROM students'
cursor.execute(sql)
students = cursor.fetchall()
for student in students:
html += '<tr>'
html += '<td>%s</td>' % student[0]
html += '<td>%s</td>' % student[1]
html += '</tr>'
html += '<table>'
函數(shù) generateHtml() 通過 SQL 語句讀取數(shù)據(jù),使用字符串拼接成一段 HTML 的 table,返回給瀏覽器。這樣的方式的缺點(diǎn)在于:HTML 代碼和 Python 代碼混合在一起,程序的可讀性很差。
針對以上問題,提出了模板的解決方案,實現(xiàn)數(shù)據(jù)與 HTML 代碼分離。以下是使用 django 的模板實現(xiàn)展示所有的學(xué)生
<table>
{% for student in students %}
<tr>
<td>{{ student[0] }}</td>
<td>{{ student[1] }}</td>
</tr>
{% endfor %}
</table>
與拼接字符串相比,使用模板生成 HTML,顯著的提高了程序的可讀性,Web 框架都配備了各種模板引擎,Web 開發(fā)者需要學(xué)習(xí)模板的語法。
4.3 數(shù)據(jù)庫 ORM
在 Web 開發(fā)中,需要訪問數(shù)據(jù)庫讀取相關(guān)數(shù)據(jù)返回給瀏覽器。通常是采用 SQL 語句訪問數(shù)據(jù)庫,例如下面的 SQL 語句獲取 name 為張三的記錄:
SELECT name, age FROM persons WHERE name = '張三'
在程序中,使用 SQL 語句訪問數(shù)據(jù),易錯、不夠直觀。因此有人提出了 ORM 技術(shù):把關(guān)系數(shù)據(jù)庫映射為對象。
面向?qū)ο缶幊毯完P(guān)系型數(shù)據(jù)庫,都是目前最流行的技術(shù)。面向?qū)ο缶幊贪阉袑嶓w看成對象(object),關(guān)系型數(shù)據(jù)庫則是采用實體之間的關(guān)系(relation)描述數(shù)據(jù)。
ORM (Object Relation Map) 是一種把關(guān)系數(shù)據(jù)庫映射成對象的技術(shù),下表總結(jié)兩者之間的對應(yīng)關(guān)系:
關(guān)系數(shù)據(jù)庫 | 面向?qū)ο?/th> |
---|---|
數(shù)據(jù)庫的表(table) | 類(class) |
記錄(record,行數(shù)據(jù)) | 對象(object) |
字段(field) | 對象的屬性(attribute) |
Python 的 Web 框架通常提供了 ORM 的功能,用于簡化對數(shù)據(jù)庫的訪問。