Flask Web開發(fā)筆記

Flask筆記

2.1初始化

Web 服務(wù)器使用一種名為 Web 服務(wù)器網(wǎng)關(guān)接口
(Web Server Gateway Interface,WSGI)的協(xié)議侥猬,把接收自客戶端的所有請求都轉(zhuǎn)交給這個對象處理胆数。程序?qū)嵗?Flask 類的對象

2.2 路由和視圖函數(shù)

程序?qū)嵗枰缹γ總€ URL 請求運(yùn)行哪些代碼越平,所以保存了一個URL到
Python 函數(shù)的映射關(guān)系。處理 URL 和函數(shù)之間關(guān)系的程序稱為路由亩歹。

在 Python 代碼中嵌入響應(yīng)字符串會導(dǎo)致代碼難以維護(hù)

2.3啟動服務(wù)器

name=='main' 是 Python 的慣常用法书幕,在這里確保直接執(zhí)行這個腳本時才啟動開發(fā)Web 服務(wù)器新荤。如果這個腳本由其他腳本引入,程序假定父級腳本會啟動不同的服務(wù)器台汇,因此不會執(zhí)行 app.run()苛骨。

服務(wù)器啟動后,會進(jìn)入輪詢苟呐,等待并處理請求痒芝。輪詢會一直運(yùn)行,直到程序停止牵素,比如按Ctrl-C 鍵严衬。

2.5請求-響應(yīng)循環(huán)
2.5.1 程序和請求上下文

Flask 使用上下文臨時把某些對象
變?yōu)槿挚稍L問。

變量名 上下文 說明
current_app 程序上下文 當(dāng)前激活程序的程序?qū)嵗?/td>
g 程序上下文 處理請求時用作臨時存儲的對象笆呆。每次請求都會重設(shè)這個變量
request 請求上下文 請求對象请琳,封裝了客戶端發(fā)出的
session 請求上下文 用戶會話,用于存儲請求之間需要“記住”的值的詞典
2.5.2 請求調(diào)度

程序收到客戶端發(fā)來的請求時赠幕,要找到處理該請求的視圖函數(shù)俄精。為了完成這個任務(wù),F(xiàn)lask
會在程序的 URL 映射中查找請求的 URL劣坊。URL 映射是 URL 和視圖函數(shù)之間的對應(yīng)關(guān)系嘀倒。
Flask 使用 app.route 修飾器或者非修飾器形式的 app.add_url_rule() 生成映射。

2.5.3 請求鉤子

有時在處理請求之前或之后執(zhí)行代碼會很有用

  • before_first_request:注冊一個函數(shù)局冰,在處理第一個請求之前運(yùn)行测蘑。
  • before_request:注冊一個函數(shù),在每次請求之前運(yùn)行康二。
  • after_request:注冊一個函數(shù)碳胳,如果沒有未處理的異常拋出,在每次請求之后運(yùn)行沫勿。
  • teardown_request:注冊一個函數(shù)挨约,即使有未處理的異常拋出味混,也在每次請求之后運(yùn)行。
2.5.4 響應(yīng)

Flask 調(diào)用視圖函數(shù)后诫惭,會將其返回值作為響應(yīng)的內(nèi)容翁锡。大多數(shù)情況下,響應(yīng)就是一個簡
單的字符串夕土,作為 HTML 頁面回送客戶端馆衔。

但 HTTP 協(xié)議需要的不僅是作為請求響應(yīng)的字符串。HTTP 響應(yīng)中一個很重要的部分是狀
態(tài)碼怨绣,F(xiàn)lask 默認(rèn)設(shè)為 200角溃,這個代碼表明請求已經(jīng)被成功處理。

3.1 Jinja2模板引擎

3.1.1 渲染模板

Flask 提供的 render_template 函數(shù)把 Jinja2 模板引擎集成到了程序中篮撑。render_template 函
數(shù)的第一個參數(shù)是模板的文件名

3.1.2 變量

在模板中使用的 {{ name }} 結(jié)構(gòu)表示一個變量减细,它是一種特殊的占位符,告訴模
板引擎這個位置的值從渲染模板時使用的數(shù)據(jù)中獲取赢笨。

Jinja2 能識別所有類型的變量未蝌,甚至是一些復(fù)雜的類型,例如列表茧妒、字典和對象树埠。在模板

可以使用過濾器修改變量,過濾器名添加在變量名之后嘶伟,中間使用豎線分隔。例如又碌,下述
模板以首字母大寫形式顯示變量 name 的值:
Hello, {{ name|capitalize }}

3.1.3 控制結(jié)構(gòu)

下面這個例子展示了如何在模板中使用條件控制語句:

{% if user %}
 Hello, {{ user }}!
{% else %}
 Hello, Stranger!
{% endif %}

另一種常見需求是在模板中渲染一組元素九昧。下例展示了如何使用 for 循環(huán)實現(xiàn)這一需求:

 <ul>
 {% for comment in comments %}
 <li>{{ comment }}</li>
 {% endfor %}
 </ul>

Jinja2 還支持宏。宏類似于 Python 代碼中的函數(shù)毕匀。

需要在多處重復(fù)使用的模板代碼片段可以寫入單獨的文件铸鹰,再包含在所有模板中,以避免
重復(fù):

{% include 'common.html' %}
3.2 使用Flask-Bootstrap集成Twitter Bootstrap

Bootstrap(http://getbootstrap.com/)是 Twitter 開發(fā)的一個開源框架皂岔,它提供的用戶界面組
件可用于創(chuàng)建整潔且具有吸引力的網(wǎng)頁蹋笼,而且這些網(wǎng)頁還能兼容所有現(xiàn)代 Web 瀏覽器。

3.3 自定義錯誤頁面

像常規(guī)路由一樣躁垛,F(xiàn)lask 允許程序使用基于模板的自定義錯誤頁面剖毯。最常見的錯誤代碼有
兩個:404,客戶端請求未知頁面或路由時顯示教馆;500逊谋,有未處理的異常時顯示。為這兩個
錯誤代碼指定自定義處理程序的方式如示例 3-6 所示土铺。

@app.errorhandler(404)
def page_not_found(e):
 return render_template('404.html'), 404
@app.errorhandler(500)
def internal_server_error(e):
 return render_template('500.html'), 500

3.4 鏈接
在模板中直接編寫簡單路由的 URL 鏈接不難胶滋,但對于包含可變部分的動態(tài)路由板鬓,在模板
中構(gòu)建正確的 URL 就很困難。而且究恤,直接編寫 URL 會對代碼中定義的路由產(chǎn)生不必要的
依賴關(guān)系俭令。如果重新定義路由,模板中的鏈接可能會失效部宿。

為了避免這些問題抄腔,F(xiàn)lask 提供了 url_for() 輔助函數(shù),它可以使用程序 URL 映射中保存的信息生成 URL窟赏。

3.5 靜態(tài)文件

默認(rèn)設(shè)置下妓柜,F(xiàn)lask 在程序根目錄中名為 static 的子目錄中尋找靜態(tài)文件。如果需要涯穷,可在static 文件夾中使用子文件夾存放文件棍掐。

3.6 使用Flask-Moment本地化日期和時間

服務(wù)器需要統(tǒng)一時間單位,這和用戶所在的地理位置無關(guān)拷况,所以一般使用協(xié)調(diào)世界時
(Coordinated Universal Time作煌,UTC).不過用戶看到 UTC 格式的時間會感到困惑,他們更希望看到當(dāng)?shù)貢r間赚瘦,而且采用當(dāng)?shù)貞T用的格式粟誓。

一個優(yōu)雅的解決方案是,把時間單位發(fā)送給 Web 瀏覽器起意,轉(zhuǎn)換成當(dāng)?shù)貢r間鹰服,然后渲染。

4.1 跨站請求偽造保護(hù)

默認(rèn)情況下揽咕,F(xiàn)lask-WTF 能保護(hù)所有表單免受跨站請求偽造(Cross-Site Request Forgery悲酷,
CSRF)的攻擊。惡意網(wǎng)站把請求發(fā)送到被攻擊者已登錄的其他網(wǎng)站時就會引發(fā) CSRF 攻擊亲善。

為了實現(xiàn) CSRF 保護(hù)设易,F(xiàn)lask-WTF 需要程序設(shè)置一個密鑰。Flask-WTF 使用這個密鑰生成
加密令牌蛹头,再用令牌驗證請求中表單數(shù)據(jù)的真?zhèn)味俜巍TO(shè)置密鑰的方法如示例 4-1 所示。

4.2 表單類

使用 Flask-WTF 時渣蜗,每個 Web 表單都由一個繼承自 Form 的類表示屠尊。這

4.3 把表單渲染成HTML

表單字段是可調(diào)用的,在模板中調(diào)用后會渲染成 HTML耕拷。假設(shè)視圖函數(shù)把一個 NameForm 實例通過參數(shù) form 傳入模板知染,在模板中可以生成一個簡單的表單,如下所示:

<form method="POST">
 {{ form.hidden_tag() }}
 {{ form.name.label }} {{ form.name() }}
 {{ form.submit() }}
</form>

4.4 在視圖函數(shù)中處理表單

不僅要渲染表單斑胜,還要接收表單中的數(shù)據(jù)

4.5 重定向和用戶會話

程序可以把數(shù)據(jù)存儲在用戶會話中控淡,在請求之間“記住”數(shù)據(jù)嫌吠。用戶會話是一種私有存儲,存在于每個連接到服務(wù)器的客戶端中

4.6 Flash消息

請求完成后掺炭,有時需要讓用戶知道狀態(tài)發(fā)生了變化辫诅。這里可以使用確認(rèn)消息、警告或者錯誤提醒涧狮。

僅調(diào)用 flash() 函數(shù)并不能把消息顯示出來炕矮,程序使用的模板要渲染這些消息。最好在基模板中渲染Flash 消息者冤,因為這樣所有頁面都能使用這些消息肤视。Flask 把get_flashed_messages() 函數(shù)開放給模板,用來獲取并渲染消息

5.1 SQL數(shù)據(jù)庫

關(guān)系型數(shù)據(jù)庫把數(shù)據(jù)存儲在表中涉枫,表模擬程序中不同的實體邢滑。

表的列數(shù)是固定的,行數(shù)是可變的愿汰。列定義表所表示的實體的數(shù)據(jù)屬性困后。

表中有個特殊的列,稱為主鍵衬廷,其值為表中各行的唯一標(biāo)識符摇予。表中還可以有稱為外鍵的列,引用同一個表或不同表中某行的主鍵吗跋。行之間的這種聯(lián)系稱為關(guān)系侧戴,這是關(guān)系型數(shù)據(jù)庫模型的基礎(chǔ)。

5.2 NoSQL數(shù)據(jù)庫

所有不遵循上節(jié)所述的關(guān)系模型的數(shù)據(jù)庫統(tǒng)稱為 NoSQL 數(shù)據(jù)庫跌宛。

使用 NoSQL 數(shù)據(jù)庫當(dāng)然也有好處救鲤。數(shù)據(jù)重復(fù)可以提升查詢速度。列出用戶及其角色的操作很簡單秩冈,因為無需聯(lián)結(jié)

5.3 使用SQL還是NoSQL

SQL 數(shù)據(jù)庫擅于用高效且緊湊的形式存儲結(jié)構(gòu)化數(shù)據(jù)。這種數(shù)據(jù)庫需要花費(fèi)大量精力保證數(shù)據(jù)的一致性斥扛。NoSQL 數(shù)據(jù)庫放寬了對這種一致性的要求入问,從而獲得性能上的優(yōu)勢。

5.4 Python數(shù)據(jù)庫框架

Flask 并不限制你使
用何種類型的數(shù)據(jù)庫包稀颁,因此可以根據(jù)自己的喜好選擇使用 MySQL芬失、Postgres、SQLite匾灶、Redis棱烂、MongoDB 或者 CouchDB。

  1. 易用性
  2. 性能
  3. 可移植性
5.5 使用Flask-SQLAlchemy管理數(shù)據(jù)庫

Flask-SQLAlchemy 是一個 Flask 擴(kuò)展阶女,簡化了在 Flask 程序中使用 SQLAlchemy 的操作颊糜。

5.6 定義模型

模型這個術(shù)語表示程序使用的持久化實體哩治。

5.7 關(guān)系

關(guān)系型數(shù)據(jù)庫使用關(guān)系把不同表中的行聯(lián)系起來。

5.8 數(shù)據(jù)庫操作
5.8.1 創(chuàng)建表

方法是使用 db.create_all()

5.8.2 插入行

db.session.add(admin_role)

5.8.3 修改行

db.session.add(admin_role)
db.session.commit()

5.8.4 刪除行

db.session.delete(mod_role)
db.session.commit()

5.8.5 查詢行

Flask-SQLAlchemy 為每個模型類都提供了 query 對象

5.9 在視圖函數(shù)中操作數(shù)據(jù)庫
5.10 集成Python shell

每次啟動 shell 會話都要導(dǎo)入數(shù)據(jù)庫實例和模型衬鱼,這真是份枯燥的工作业筏。為了避免一直重復(fù)導(dǎo)入,我們可以做些配置鸟赫,讓 Flask-Script 的 shell 命令自動導(dǎo)入特定的對象蒜胖。

5.11 使用Flask-Migrate實現(xiàn)數(shù)據(jù)庫遷移
7.1 項目結(jié)構(gòu)

多文件 Flask 程序的基本結(jié)構(gòu)

|-flasky
 |-app/
    |-templates/
    |-static/
    |-main/
        |-__init__.py
        |-errors.py
        |-forms.py
        |-views.py
    |-__init__.py
    |-email.py
    |-models.py
 |-migrations/
 |-tests/
    |-__init__.py
    |-test*.py
 |-venv/
 |-requirements.txt
 |-config.py
 |-manage.py

這種結(jié)構(gòu)有 4 個頂級文件夾:

  • Flask 程序一般都保存在名為 app 的包中;
  • 和之前一樣抛蚤,migrations 文件夾包含數(shù)據(jù)庫遷移腳本台谢;
  • 單元測試編寫在 tests 包中;
  • 和之前一樣岁经,venv 文件夾包含 Python 虛擬環(huán)境

同時還創(chuàng)建了一些新文件:

  • requirements.txt 列出了所有依賴包朋沮,便于在其他電腦中重新生成相同的虛擬環(huán)境;
  • requirements.txt 列出了所有依賴包蒿偎,便于在其他電腦中重新生成相同的虛擬環(huán)境朽们;
  • manage.py 用于啟動程序以及其他的程序任務(wù)。
7.2 配置選項

程序經(jīng)常需要設(shè)定多個配置诉位。這方面最好的例子就是開發(fā)骑脱、測試和生產(chǎn)環(huán)境要使用不同的數(shù)據(jù)庫,這樣才不會彼此影響苍糠。

7.3 程序包

程序包用來保存程序的所有代碼叁丧、模板和靜態(tài)文件。我們可以把這個包直接稱為app

7.3.1 使用程序工廠函數(shù)

在單個文件中開發(fā)程序很方便岳瞭,但卻有個很大的缺點拥娄,因為程序在全局作用域中創(chuàng)建,所以無法動態(tài)修改配置瞳筏。運(yùn)行腳本時稚瘾,程序?qū)嵗呀?jīng)創(chuàng)建,再修改配置為時已晚姚炕。這一點對單元測試尤其重要摊欠,因為有時為了提高測試覆蓋度,必須在不同的配置環(huán)境中運(yùn)行程序柱宦。

這個問題的解決方法是延遲創(chuàng)建程序?qū)嵗┙罚褎?chuàng)建過程移到可顯式調(diào)用的工廠函數(shù)中。這種方法不僅可以給腳本留出配置程序的時間掸刊,還能夠創(chuàng)建多個程序?qū)嵗飧猓@些實例有時在測試中非常有用。

7.3.2 在藍(lán)本中實現(xiàn)程序功能

藍(lán)本和程序類似,也可以定義路由石窑。不同的
是牌芋,在藍(lán)本中定義的路由處于休眠狀態(tài),直到藍(lán)本注冊到程序上后尼斧,路由才真正成為程序的一部分姜贡。使用位于全局作用域中的藍(lán)本時,定義路由的方法幾乎和單腳本程序一樣棺棵。

7.4 啟動腳本

頂級文件夾中的 manage.py 文件用于啟動程序楼咳。

7.5 需求文件

程序中必須包含一個 requirements.txt 文件,用于記錄所有依賴包及其精確的版本號烛恤。如果要在另一臺電腦上重新生成虛擬環(huán)境母怜,這個文件的重要性就體現(xiàn)出來了,例如部署程序時使用的電腦缚柏。pip 可以使用如下命令自動生成這個文件:

(venv) $ pip freeze >requirements.txt
7.6 單元測試
7.7 創(chuàng)建數(shù)據(jù)庫
8.1 Flask的認(rèn)證擴(kuò)展
8.2 密碼安全性
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苹熏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子币喧,更是在濱河造成了極大的恐慌轨域,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杀餐,死亡現(xiàn)場離奇詭異干发,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)史翘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門枉长,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人琼讽,你說我怎么就攤上這事必峰。” “怎么了钻蹬?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵吼蚁,是天一觀的道長。 經(jīng)常有香客問我问欠,道長肝匆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任溅潜,我火速辦了婚禮,結(jié)果婚禮上薪伏,老公的妹妹穿的比我還像新娘滚澜。我一直安慰自己,他們只是感情好嫁怀,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布设捐。 她就那樣靜靜地躺著借浊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪萝招。 梳的紋絲不亂的頭發(fā)上蚂斤,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機(jī)與錄音槐沼,去河邊找鬼曙蒸。 笑死,一個胖子當(dāng)著我的面吹牛岗钩,可吹牛的內(nèi)容都是我干的纽窟。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼兼吓,長吁一口氣:“原來是場噩夢啊……” “哼臂港!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起视搏,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤审孽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后浑娜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體佑力,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年棚愤,在試婚紗的時候發(fā)現(xiàn)自己被綠了搓萧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡宛畦,死狀恐怖瘸洛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情次和,我是刑警寧澤反肋,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站踏施,受9級特大地震影響石蔗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜畅形,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一养距、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧日熬,春花似錦棍厌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敬肚。三九已至,卻和暖如春束析,著一層夾襖步出監(jiān)牢的瞬間艳馒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工员寇, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留弄慰,地道東北人。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓丁恭,卻偏偏與公主長得像曹动,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子牲览,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 22年12月更新:個人網(wǎng)站關(guān)停墓陈,如果仍舊對舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,170評論 22 257
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)第献,斷路器贡必,智...
    卡卡羅2017閱讀 134,639評論 18 139
  • 第三章 模板 序 為什么要分離 易于維護(hù)的代碼,關(guān)鍵在于保持簡單的結(jié)構(gòu)庸毫。而我們之前編寫的hello.py雖然簡單仔拟,...
    科幻經(jīng)典閱讀 1,529評論 0 6
  • 第三章 模板(Templates) 編寫易于維護(hù)的程序的要點在于書寫干凈、良好結(jié)構(gòu)的代碼飒赃。你以前所見的代碼都過于...
    易木成華閱讀 1,124評論 0 2
  • 這幾天想學(xué)新東西利花,就看了flask框架,本身對python不太了解载佳,網(wǎng)上的很多教程看了炒事,總是在某些地方卡住。翻到一...
    易木成華閱讀 2,224評論 0 11