1. 程式人生 > 其它 >flask訪問404_Flask鉤子函式

flask訪問404_Flask鉤子函式

技術標籤:flask訪問404

鉤子函式

1.什麼是鉤子函式

在正常執行的程式碼前後,插入一段想要執行的程式碼,這稱為鉤子函式.

2.Flask 中的鉤子函式

上一篇分析了原始碼flask/app.py中的Flask() 類,其實它除了實現了應用上下文,請求上下文之外,還實現了一些常用的鉤子hook 函式.

常見的鉤子函式有:

鉤子函式描述
before_first_request在處理第一個請求前執行,比如連線資料庫操作
before_request在每次執行請求前執行,比如許可權校驗
after_request在每次請求之後呼叫,前提是沒有異常丟擲
errorhandler在訪問應用出錯時,根據錯誤碼,做一些定製
context_processor上下文鉤子,返回一個字典物件,可以在jinja 模板中使用
teardown_request在響應銷燬時,執行一個函式
teardown_appcontext不管時候有異常,當應用上下文被移除時,執行的函式.

1.before_first_request

只有在處理第一次請求之前會執行,之後都不會執行.

應用場景:可以載入一些函式,用來對網站進行一些測試,檢查,如果發現異常,則截斷後續的請求,將整個Flask 應用停止執行.

fromflaskimportFlask

app=Flask(__name__)
app.config.update({
'DEBUG':True,
'AUTO_TEMPLATES_RELOAD':True
})

@app.route('/')
defindex():
return'HelloWorld!'

@app.before_first_request
deftest_app():
print('測試伺服器執行')

if__name__=='__main__':
app.run()

輸出:

127.0.0.1--"GET/HTTP/1.1"200-
測試伺服器執行
127.0.0.1--"GET/HTTP/1.1"200-

2.before_request

在每個請求之前都會執行的鉤子.

應用場景:共享session 的鑑權函式,請求黑白名單過濾,根據endpoint

進行請求等.

fromflaskimportBlueprint,request


bp=Blueprint('api',__name__,url_prefix='/api/')

required={
'api_register':['email','username','password']
}

@bp.before_request
defbefore():
ifnotrequest.is_json:
print(request.endpoint)
print(request.json)
return'請使用json風格的引數訪問'
try:
ifrequest.endpointinrequired:
ifrequest.method=='POST':
missparam_list=[xforxinrequired[request.endpoint]ifxnotinrequest.json.keys()]
iflen(missparam_list)>0:
return'缺少引數'
exceptExceptionase:
print(e)
return"{}???".format(e)

@bp.route('/test/')
deftest():
ifrequest.method=='POST':
return'test'

@bp.route('/api_register/')
defregister():
return'hello'

比如在驗證session,來檢視使用者是否已經登入

fromflaskimportFlask,session,g
frommodel.apiimportbp
fromosimporturandom

app=Flask(__name__)
app.config.update({
'DEBUG':True,
'AUTO_TEMPLATES_RELOAD':True,
'SECRET_KEY':urandom(24)
})

@app.route('/')
defindex():
session['name']='Python'
return'HelloWorld!'

@app.before_first_request
deftest_app():
print('測試伺服器執行')

app.register_blueprint(bp)

@app.before_request
defbefore():
name=session.get('name')
ifname:
g.name=name

@app.route('/first/')
deffirst():
ifg.name:
return'已登入'
else:
return'請登入'

if__name__=='__main__':
app.run()

3.after_request

請求完成時執行,但是必須傳入一個引數來接受響應物件,並在最後的return 這個引數,也就是響應內容.

場景:一般用於格式化響應結果,包括響應請求頭,響應的格式等.

fromflaskimportFlask,session,g
frommodel.apiimportbp
fromosimporturandom

app=Flask(__name__)
app.config.update({
'DEBUG':True,
'AUTO_TEMPLATES_RELOAD':True,
'SECRET_KEY':urandom(24)
})

@app.route('/')
defindex():
session['name']='Python'
return'HelloWorld!'

@app.before_first_request
deftest_app():
print('測試伺服器執行')

app.register_blueprint(bp)

@app.before_request
defbefore():
name=session.get('name')
ifname:
g.name=name

@app.route('/first/')
deffirst():
ifg.name:
return'已登入'
else:
return'請登入'
@app.after_request
defafter(response):
response.headers['test']='test'
returnresponse

if__name__=='__main__':
app.run()

訪問127.0.0.1/first/,檢視響應頭.

c759c5dd5a92a18877f9887edf17d31d.png

4.errorhandler

當訪問出錯時,根據錯誤響應碼,進行一些定製化的操作,比如返回404 頁面.

場景: 定製化錯誤資訊,404 ,500 等.

@app.errorhandler
defpage_not_fond(error):
returnrender_template('404.html'),404

訪問不存在的頁面時,它會返回定義的404.html

❯curlhttp://127.0.0.1:5000/sdf
HTMLPUBLIC"-//W3C//DTDHTML3.2Final//EN">
404NotFound

NotFound


TherequestedURLwasnotfoundontheserver.IfyouenteredtheURLmanuallypleasecheckyourspellingandtryagain.


也可以在函式中手動丟擲錯誤,這需要使用到abort() 函式

fromflaskimportabort
@app.route('/app/')
defmy_app()
#手動彈出一個錯誤abort(404)return'test'

訪問同樣會訪問到404.html

❯curlhttp://127.0.0.1:5000/app/
HTMLPUBLIC"-//W3C//DTDHTML3.2Final//EN">
404NotFound

NotFound


TherequestedURLwasnotfoundontheserver.IfyouenteredtheURLmanuallypleasecheckyourspellingandtryagain.


5.context_processor

將一些資料按照字典的格式返回,可以在jinja 模板中使用.這樣就不用在每個檢視函式中都去返回一次render_template('xxx.html',info=xxx)

需要注意的是,這個函式必須返回一個字典物件,不管最後的判斷函式是怎麼樣的.

場景:適用多個頁面返回一個同樣的值.比如登入後,在每個頁面的標頭都會顯示使用者的使用者名稱.

#app.py
@app.context_processor
defcontext():
#表示登入
ifg.name:
return{'username':'Jack'}
else:
return{}

@app.route('/test1/')
deftest1():
returnrender_template('test1.html')

@app.route('/test2/')
deftest2():
returnrender_template('test2.html')

test1.html\test2.html 中接受username

{# test1.html, test2.html# }
{{ username}}

6.teardown_request

在響應銷燬時,執行一個繫結的函式.

  • after_requtst:每一個請求之後繫結一個函式,如果請求沒有異常
  • teardown_request:每一個請求之後繫結一個函式,即是有異常

場景:銷燬資料庫db 連線

@app.teardown_request
defteardown():
db=getattr(g,'database',None)
ifdbisnotNone:
db.close()

7.teardown_appcontext

不管是否有異常,當app 的上下文被移除之後執行的函式,可以進行資料庫的提交或者回滾.

@app.teardown_appcontext
defteardown(cmd=None):
ifcmdisNone:
db.session.commit()
else:
db.session.rollback()
db.session.remove()
- END -