Flask-Grundlegende Inhalte-Drei

I沾谓、請求鉤子

什么是請求鉤子?在客戶端和服務(wù)器交互的過程中戳鹅,有些準備工作或掃尾工作需要統(tǒng)一處理均驶,為了讓每個視圖函數(shù)避免編寫重復(fù)功能的代碼,flask提供了統(tǒng)一的接口可以添加這些處理函數(shù)枫虏,即請求鉤子妇穴。

比如:請求開始時的db_connect、auth認證隶债,或者結(jié)束時的置頂數(shù)據(jù)的交互格式腾它。

先回顧一下flask對請求的處理流程:

接收請求--》創(chuàng)建請求上下文--》請求上下文入棧--》創(chuàng)建該請求的應(yīng)用上下文--》應(yīng)用上下文入棧--》處理邏輯--》請求上下文出棧--》應(yīng)用上下文出棧

看了這個過程,flask放置請求鉤子的位置有:處理邏輯之前死讹,處理邏輯之后瞒滴,應(yīng)用上下文出棧之前。

那么為什么要設(shè)計請求鉤子呢赞警?
為了讓每個視圖函數(shù)避免編寫重復(fù)功能的代碼妓忍,F(xiàn)lask提供了通用設(shè)置等功能,即請求鉤子愧旦。請求鉤子是通過裝飾器的形式實現(xiàn)世剖,F(xiàn)lask支持五種請求鉤子:
1.before_first_request
在第一個請求前被調(diào)用(在處理第一個請求之前執(zhí)行),可在此方法內(nèi)做一些初始化操作
2.before_request
在每次請求前執(zhí)行笤虫,如果在某修飾的函數(shù)中返回了一個響應(yīng)(response)旁瘫,視圖函數(shù)將不再被調(diào)用。
3.after_request
在每次請求后(如果沒有拋出錯誤)執(zhí)行琼蚯,并且把視圖函數(shù)所生成的響應(yīng)傳入境蜕。可接收一個參數(shù):視圖函數(shù)做出的相應(yīng)凌停,在此函數(shù)中可以對響應(yīng)值在返回之前做最后一步修改處理粱年,需要將參數(shù)中的相應(yīng)在此參數(shù)中進行返回。在此方法中可對響應(yīng)做最后一步統(tǒng)一處理罚拟。
4.teardown_request
在每次請求后執(zhí)行台诗;接收一個參數(shù)(錯誤信息)完箩,如果有相關(guān)錯誤拋出,需要設(shè)置flask的配置DEBUG=False拉队,teardown_request才會接收到異常對象
5.teardown_appcontext
在應(yīng)用上下文從棧中彈出之前運行

首先創(chuàng)建一個新的app弊知,demo_gouzi.py并填充

from flask import Flask

app = Flask(__name__)


@app.before_first_request
def before_first_request():
    print('before_first_request')


@app.before_request
def before_request():
    print('before_request')


@app.after_request
def after_request(response):
    print('after_request')
    response.headers['Content-Type'] = "application/json"
    return response


@app.teardown_request
def teardown_request(response):
    print('teardown_request')


@app.route('/')
def index():
    return 'index'


if __name__ == '__main__':
    app.run(debug=False)

我們運行下服務(wù),觀察執(zhí)行結(jié)果


執(zhí)行過程

after_request的執(zhí)行結(jié)果

II粱快、request對象屬性

語法 描述
request.scheme 代表請求的方案,http或者https
request.path 請求的路徑
request.method 表示請求使用的http方法,GET或者POST請求
request.encoding 表示提交數(shù)據(jù)的編碼方式
request.GET 獲取GET請求
request.POST 獲取post的請求,比如前端提交的用戶密碼,可以通過request.POST.get()來獲取 另外:如果使用 POST 上傳文件的話秩彤,文件信息將包含在 FILES 屬性中
request.cookies 包含所有的cookie
request.session 一個既可讀又可寫的類似于字典的對象,表示當(dāng)前的會話

III事哭、狀態(tài)保持

因為http是一種無狀態(tài)協(xié)議漫雷,不保持某一次請求所產(chǎn)生的信息,如想實現(xiàn)狀態(tài)保持鳍咱,在開發(fā)中解決方式有:

cookie:數(shù)據(jù)存儲在客戶端降盹,節(jié)省服務(wù)器空間,但是不安全
session:會話谤辜,數(shù)據(jù)存儲在服務(wù)器端
對于無狀態(tài)協(xié)議的理解蓄坏,看做以下五條
1、協(xié)議對于事務(wù)處理沒有記憶能力
2丑念、對同一個url請求沒有上下文關(guān)系
3涡戳、每次的請求都是獨立的,它的執(zhí)行情況和結(jié)果與前面的請求和之后的請求是無直接關(guān)系的脯倚,它不會受前面的請求應(yīng)答情況直接影響妹蔽,也不會直接影響后面的請求應(yīng)答情況
4、服務(wù)器中沒有保存客戶端的狀態(tài)挠将,客戶端必須每次帶上自己的狀態(tài)去請求服務(wù)器
5、人生若只如初見:比如商品加入購物車编整,重登后購物車里的東西無了

在Django中我們接觸過cookie和session舔稀,下面我們看看在Flask中如何使它們

1、cookie
cookie在flask中的使用掌测,我們以如下示例展示:
①設(shè)置cookie

# make_response相當(dāng)于Django中的http_response
from flask import  make_response

@app.route('/cookie')
def set_cookie():
    res = make_response('this is to set cookie')
    res.set_cookie('username', 'laoma')
    return res

啟動服務(wù)内贮,進入http://127.0.0.1:5000/cookie觀察結(jié)果

cookie

注:cookie是有時間限制的,超過時間會過期汞斧,我們可以自己設(shè)計cookie的時間(利用max_age關(guān)鍵字)

# 設(shè)計cookie的時間夜郁,時間戳單位為:秒
res.set_cookie('username', 'laoma', max_age=3600)

②獲取cookie

from flask import request

@app.route('/request')
def get_cookie():
    res = request.cookies.get('username')
    return res

啟動服務(wù)觀察結(jié)果

2、session
session會話主要用于存儲敏感涉密信息粘勒,例如:個人信息竞端、賬戶余額、驗證碼等問題庙睡,session依賴于cookie事富,在TensorFlow中技俐,也會使用session盡管和web中的session有所不同,但也可理解為會話方式统台。
下面我們將使用session

from flask import Flask, redirect, url_for
from flask import session

# 需要設(shè)置secret_key
app.secret_key = '9999999'


@app.route('/index1')
def index1():
    session['chase'] = '9999'
    return redirect(url_for('index'))

# ‘0’為設(shè)置的默認值雕擂,默認值必須設(shè)置否則會報500錯誤
@app.route('/')
def index():
    return session.get('chase', '0')

Session, Cookies以及一些第三方擴展都會用到SECRET_KEY值,這是一個比較重要的配置值贱勃,應(yīng)該盡可能設(shè)置為一個很難猜到的值井赌,隨機值更佳。隨機的問題在于很難判斷什么是真隨機贵扰。一個密鑰應(yīng)該足夠隨機仇穗。你的操作系統(tǒng)可以基于一個密碼隨機生成器來生成漂亮的隨機值,這個值可以用來做密鑰拔鹰;

SECRET_KEY配置變量是通用密鑰, 可在 Flask 和多個第三方擴展中使用. 如其名所示, 加密的強度取決于變量值的機密度. 不同的程序要使用不同的密鑰, 而且要保證其他人不知道你所用的字符串.其主要作用應(yīng)該是在各種加密過程中加鹽以增加安全性仪缸。在實際應(yīng)用中最好將這個參數(shù)存儲為系統(tǒng)環(huán)境變量。當(dāng)然我們也可以利用加密哈希列肢,就是讓cookie變得“安全”的字段恰画。服務(wù)器向我們發(fā)送最新的會話數(shù)據(jù)之前,會結(jié)合我們的會話數(shù)據(jù)瓷马、當(dāng)前時間戳以及服務(wù)器的私鑰來計算哈希從而加密session页眯,使得會話變得安全捉偏。

快速入門中的 “ 會話”部分對應(yīng)設(shè)置哪種服務(wù)器端機密提供了很好的建議。加密取決于機密;如果你沒有設(shè)置要使用的加密服務(wù)器端密碼雹食,那么每個人都可以破壞你的加密;就像你計算機的密碼一樣啥辨。秘密加上要簽名的數(shù)據(jù)用于創(chuàng)建簽名字符串介返,使用密碼哈希算法很難重新創(chuàng)建值;僅當(dāng)你具有完全相同的機密且原始數(shù)據(jù)時蒋伦,你才能重新創(chuàng)建此值弓摘,讓Flask檢測是否未經(jīng)許可對任何內(nèi)容進行了更改。由于Flask永遠不會將秘密包含在發(fā)送給客戶端的數(shù)據(jù)中痕届,因此客戶端無法篡改會話數(shù)據(jù)韧献,并希望產(chǎn)生新的有效簽名。

Flask盡量使用該itsdangerous庫來完成所有艱苦的工作研叫;會話使用帶有自定義JSON序列化程序的itsdangerous.URLSafeTimedSerializer類锤窑。

3、上下文
①請求上下文request context
request和session都屬于請求上下文對象嚷炉。request:封裝了HTTP請求的內(nèi)容渊啰,針對的是http請求。舉例:user = request.args.get('user')申屹,獲取的是get請求的參數(shù)虽抄。
這不再做過多介紹

②應(yīng)用上下文application context
在發(fā)送請求時走搁,我們可以通過上下文發(fā)送全局對象,例如app.name

current_app和g都屬于應(yīng)用上下文對象迈窟。
1私植、current_app:表示當(dāng)前運行程序文件的程序?qū)嵗?br> 2、g:(global) 處理請求時车酣,用于臨時存儲的對象曲稼,每次請求都會重設(shè)這個變量。比如:我們可以獲取一些臨時請求的用戶信息湖员。

當(dāng)調(diào)用app = Flask(_name_)的時候贫悄,創(chuàng)建了程序應(yīng)用對象app;
request 在每次http請求發(fā)生時娘摔,WSGI server調(diào)用Flask.call()窄坦;然后在Flask內(nèi)部創(chuàng)建的request對象;
app的生命周期大于request和g凳寺,一個app存活期間鸭津,可能發(fā)生多次http請求,所以就會有多個request和g肠缨。
最終傳入視圖函數(shù)逆趋,通過return、redirect或render_template生成response對象晒奕,返回給客戶端闻书。

區(qū)別: 請求上下文:保存了客戶端和服務(wù)器交互的數(shù)據(jù)。 應(yīng)用上下文:在flask程序運行過程中脑慧,保存的一些配置信息魄眉,比如程序文件名、數(shù)據(jù)庫的連接闷袒、用戶信息等坑律。

一個操作實例:

from flask import current_app, g

@app.route('/')
def index():
    print(current_app.name)
    print(g.ip)
    return session.get('chase', '0')

IV、上下文隔離原理

Flask主要是借助werkzueg來實現(xiàn)的霜运,其中請求之間隔離的方式借助了庫中Local、LocalStack蒋腮、LocalProxy 三個類淘捡,下面將逐一介紹

1、Local:
首先local添加了一個storage字典用來存儲添加的屬性池摧,當(dāng)給local對象進行添加屬性會自動根據(jù)get_ident方法獲取當(dāng)前的線程焦除、進程,鍵為線程作彤、進程ID號膘魄,值為添加的屬性乌逐,同理當(dāng)取值時,會自動判斷當(dāng)前的環(huán)境來取值, 類似于threading中的local
2创葡、LocalStack:
LocalStack基于local實現(xiàn)了一個‘先進晚出’的棧結(jié)構(gòu)浙踢,內(nèi)部通過為每個線程、進程添加
stack屬性來存儲數(shù)據(jù)灿渴,存儲數(shù)據(jù)的容器為list洛波,值得注意是每次添加值、取值得時候內(nèi)部會自動判斷當(dāng)前的線程骚露、進程環(huán)境為每個線程蹬挤、進程床架一個單獨的容器,這也是不同請求之間實現(xiàn)隔離的主要原因棘幸,同樣的current_app 當(dāng)前的應(yīng)用上下文也用到了類似的方式來管理焰扳,也就是說每個請求都有自己的應(yīng)用上下文,請求的每次入棧都會判斷當(dāng)前的應(yīng)用上下文误续,如果沒有創(chuàng)建應(yīng)用上下文吨悍,則創(chuàng)建對應(yīng)的上下文壓入棧也就是_app_ctx_stack,request對應(yīng)的則是_request_ctx_stack
3女嘲、LocalProxy:
作為一種代理模式的實現(xiàn)畜份,我們通過查看源碼發(fā)現(xiàn),LocalProxy實現(xiàn)了重寫了大量的類的‘魔術(shù)’方法欣尼,其實localproxy主要就是對對象爆雹、方法進行了包裝,通過localproxy進行過渡可以直接操作目標(biāo)對象LocalProxy對_lookup_req_object方法進行了包裝愕鼓,當(dāng)我們訪問request屬性的時候钙态,由于LocalProxy重寫了setattr getattr等特殊方法,在執(zhí)行的時候會調(diào)用_get_cuurent_object方法且直接執(zhí)行了self.__local()方法其實也就是包裝之前的_lookup_req_object菇晃,通過這個方法可以獲取全局請求上下文棧頂?shù)恼埱笊舷挛闹械膔equest屬性册倒,注意_request_ctx_stack中存儲的是請求上下文(Request_Context),我們每次操作的request其實是Request_Context的一個屬性

\color{red}{下面給出Flask的上下文流程圖}
\color{violet}{上文}

上文

\color{violet}{下文}
下文

此處編輯匆忙磺送,存有大量借鑒驻子,而在此之后作者還會更新該內(nèi)容
上述內(nèi)容分別:
源碼解析轉(zhuǎn)載于:https://www.cnblogs.com/alplf123/p/10517057.html
流程圖轉(zhuǎn)載于:https://www.cnblogs.com/baijinshuo/p/10264326.html


V、初探模板 Jinja2

我們先建立一個flask_templates.py文件估灿,建立應(yīng)用來體驗一下Flask如何調(diào)用模板


app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html')


if __name__ == '__main__':
    app.run()

index.html的內(nèi)容為

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
INDEX
</body>
</html>

我們啟動一下服務(wù)崇呵,看看模板是否被調(diào)用

我們來介紹一下Jinja2
Jinja2是Python下一個被廣泛應(yīng)用的模版引擎,他的設(shè)計思想來源于Django的模板引擎馅袁,并擴展了其語法和一系列強大的功能域慷。其中最顯著的一個是增加了沙箱執(zhí)行功能和可選的自動轉(zhuǎn)義功能,這對大多應(yīng)用的安全性來說是非常重要的。它基于unicode并能在python2.4之后的版本運行犹褒,包括python3(來源于百度百科)

其中Jinja2的模板語法與Django的模板內(nèi)容基本相似

在Jinja2中抵窒,存在三種語法:
1、控制結(jié)構(gòu){% %}
2叠骑、變量取值{{ }}
Jinja2模板中使用 {{ }} 語法表示一個變量李皇,它是一種特殊的占位符。當(dāng)利用Jinja2進行渲染的時候座云,它會把這些特殊的占位符進行填充/替換疙赠,Jinja2支持python中所有的Python數(shù)據(jù)類型比如列表、字段朦拖、對象等圃阳。
3、注釋 {# #}

@app.route('/')
def index():
    res = {'my_str': 'my', 'my_int': 1, 'my_list': [1, 2, 3], "my_dict": {"on": "day"}}
    return render_template('index.html', my_str='my', my_int=1, my_list=[1, 2, 3], my_dict={"on": "day"})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Jinja2模板</h1>
{{ my_str }}<br>
{{ my_int }}<br>
{{ my_list }}<br>
{{ my_dict }}<br>
<hr>
my_int + 10 = {{ my_int + 10 }}<br>
my_int _ my_list[0] = {{ my_int + my_list[0] }}<br>
list[2] = {{ my_list.2 }}<br>
my_dict['on'] = {{ my_dict['on'] }}<br>
my_dict['on'] = {{ my_dict.on }}
</body>
</html>

啟動服務(wù)觀察結(jié)果璧帝,其語法與python內(nèi)的語法十分相似捍岳。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市睬隶,隨后出現(xiàn)的幾起案子锣夹,更是在濱河造成了極大的恐慌,老刑警劉巖苏潜,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件银萍,死亡現(xiàn)場離奇詭異,居然都是意外死亡恤左,警方通過查閱死者的電腦和手機贴唇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來飞袋,“玉大人戳气,你說我怎么就攤上這事∏裳迹” “怎么了瓶您?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纲仍。 經(jīng)常有香客問我呀袱,道長,這世上最難降的妖魔是什么郑叠? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任夜赵,我火速辦了婚禮,結(jié)果婚禮上锻拘,老公的妹妹穿的比我還像新娘油吭。我一直安慰自己,他們只是感情好署拟,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布婉宰。 她就那樣靜靜地躺著,像睡著了一般推穷。 火紅的嫁衣襯著肌膚如雪心包。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天馒铃,我揣著相機與錄音蟹腾,去河邊找鬼。 笑死区宇,一個胖子當(dāng)著我的面吹牛娃殖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播议谷,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼炉爆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了卧晓?” 一聲冷哼從身側(cè)響起芬首,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逼裆,沒想到半個月后郁稍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡胜宇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年耀怜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掸屡。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡封寞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仅财,到底是詐尸還是另有隱情狈究,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布盏求,位于F島的核電站抖锥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碎罚。R本人自食惡果不足惜磅废,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荆烈。 院中可真熱鬧拯勉,春花似錦竟趾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至导绷,卻和暖如春犀勒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背妥曲。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工贾费, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人檐盟。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓褂萧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親葵萎。 傳聞我的和親對象是個殘疾皇子箱玷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348