flask內容學習第二天
異常的捕獲
1 from flask import Flask 2 from flask import abort 3 4 app = Flask(__name__) 5 6 7 @app.route(‘/‘) 8 def hello_world(): 9 return ‘Hello World!‘ 10 11 12 @app.route("/demo1") 13 def demo1(): 14 # 主動http狀態碼 15 abort(404) 16 return "demo1" 17 18 19 # 使用裝飾器來捕獲異常指定的狀態碼和異常View Code20 @app.errorhandler(404) 21 def page_not_fund(error): 22 print(error) 23 return "頁面不存在" 24 25 26 @app.route("/demo2") 27 def div_demo2(): 28 a = 5 29 b = 0 30 return a / b 31 32 33 # 使用錯誤捕獲來捕獲除數不能為0的的錯誤 34 @app.errorhandler(ZeroDivisionError) 35 def Zero_Division_Error(error): 36 print(error) 37 return "除數不能為0" 38 39 40 # 第二種捕獲異常的方式 41 # def page_not_found(error): 42 # return ‘你訪問的頁面不存在‘, 404 43 # app.error_handler_spec[None][404] = page_not_found 44 45 46 47 if __name__ == ‘__main__‘: 48 app.run(debug=True)
註冊一個處理程序錯誤的裝飾器,當程序拋出指定錯誤狀態碼的時候會調用裝飾器所裝飾的方法(除了捕獲異常的狀態碼之外還可以捕獲指定的異常)
flask中的請求鉤子
1 #! /usr/bin/env python 2 # *-* coding: utf-8 *-* 3 4 from flask import Flask 5 6 app = Flask(__name__) 7 8 9 @app.before_first_request 10 def before_first_request(): 11 print("before_first_request") 12 13 14 @app.before_request 15 def before_request(): 16 print("before_request") 17 18 19 @app.after_request 20 def after_request(response): 21 print("response", response) 22 print("after_request") 23 return response 24 25 26 # 在請求之後可以被執行,如果有異常會將此異常傳入到這個函數來做處理 27 @app.teardown_request 28 def teardown_request(error): 29 print(error) 30 print("teardown_request") 31 32 33 @app.route(‘/‘) 34 def index(): 35 print("index", index) 36 return ‘index‘ 37 38 39 if __name__ == ‘__main__‘: 40 app.run(debug=True)View Code
before_first_request(在處理第一個請求前執行,後續的執行過程就不會再執行了)
before_request(每次發起請求前都會執行,如果在某個修飾函數中返回一個響應,視圖函數將不再被調用)
after_request
(
沒有拋出異常,則在每次請求後會執行
接收一個參數:視圖函數做出的響應;
在此函數中可以對視圖函數做出的響應做最後一步的處理;
需要將參數中的響應在此函數中返回
)
teardown_request
(
每次請求之後都會執行;
接收一個參數:如果拋出異常,則參數會捕捉到這個異常;
)
1 #! /usr/bin/env python 2 # *-* coding: utf-8 *-* 3 4 from flask import Flask,request 5 from werkzeug.serving import run_simple 6 7 app = Flask(__name__) 8 9 10 @app.route(‘/‘) 11 def hello_world(): 12 return ‘Hello World!‘ 13 14 @app.route(‘/index‘, methods=["POST",]) 15 def index(): 16 print(request.method) 17 return ‘index index!‘ 18 19 # rule 視圖函數和酷遊關系的映射關系 20 # map rule的集合 21 # BaseConverter匹配路由匹配的規則 22 # MapAdapter協調以上的路由匹配的工作 23 24 25 if __name__ == ‘__main__‘: 26 print(app.url_map) 27 app.run(debug=True)裝飾器路由功能的實現
Werkzeug庫的 routing 模塊負責實現 URL 解析。不同的 URL 對應不同的視圖函數,routing模塊會對請求信息的URL進行解析,匹配到URL對應的視圖函數,執行該函數以此生成一個響應信息。
routing模塊內部有:
- Rule類
- 用來構造不同的URL模式的對象,路由URL規則
- Map類
- 存儲所有的URL規則和一些配置參數
- BaseConverter的子類
- 負責定義匹配規則
- MapAdapter類
- 負責協調Rule做具體的匹配的工作
1 #! /usr/bin/env python 2 # *-* coding: utf-8 *-* 3 4 5 from flask import Flask 6 from flask import request 7 8 app = Flask(__name__) 9 10 11 @app.route(‘/index‘, methods=["GET", "POST"]) 12 def index(): 13 return ‘Hello World!‘ 14 15 16 @app.route("/args", methods=["GET", "POST"]) 17 def args(): 18 # get方式地址欄傳遞參數 19 print(request.form.get("name")) 20 print(request.form.get("age")) 21 # post方式請求體中傳遞參數 22 print(request.args.get("name")) 23 print(request.args.get("age")) 24 return "success" 25 26 27 @app.route("/file", methods=["POST"]) 28 def up_load_file(): 29 print(request.method) 30 pic = request.files.get("pic") 31 pic.save("./static/aaaa.png") 32 return "success" 33 34 35 if __name__ == ‘__main__‘: 36 app.run(debug=True)request的使用
request是flask中代表當前請求的request對象,是一個全局的請求上下文的一個變量(可以理解成為一個全局變量,在視圖函數中可以直接使用,可以取到當前請求)。
備註:在地址欄中請求數據的方式可以用args的方式去在request中取值,如果在form表單中的數據需要在form中取值。
cookie的設置
1 #! /usr/bin/env python 2 # *-* coding: utf-8 *-* 3 4 from flask import Flask 5 from flask import request 6 from flask import make_response 7 8 app = Flask(__name__) 9 10 11 # 獲取cookies 12 @app.route(‘/index‘) 13 def index(): 14 username = request.cookies.get("username") 15 user_id = request.cookies.get("user_id") 16 return ‘%s---%s‘ % (username, user_id) 17 18 19 # 設置cookies 20 @app.route("/login") 21 def login(): 22 response = make_response("success") 23 response.set_cookie("username", "xiaoimng", max_age=3600) 24 response.set_cookie("user_id", "1", max_age=3600) 25 return response 26 27 28 # 刪除cookies 29 @app.route("/logout") 30 def logout(): 31 32 response = make_response("刪除cookies成功") 33 response.delete_cookie("user_id") 34 response.delete_cookie("username") 35 return response 36 37 38 if __name__ == ‘__main__‘: 39 app.run(debug=True)cookie的設置
備註:
1,cookie的設置是在response中進行設置,在request中取值;
2,http是一種無狀態的協議,瀏覽器在請求服務器的時候是無狀態的,
無狀態的原因是:
瀏覽器與服務器通過socket進行通信,服務器會將請求結果返回給瀏覽器,請求完畢後服務器都會將通信套接字關閉,並且服務器在關閉套接字之後就會銷毀請求的頁面的對象;
有時需要保持瀏覽器的狀態,比如用戶的登錄狀態,和瀏覽過的信息等;
無狀態協議
1,協議對事物的處理沒有記憶的功能;
2,對於同一個url請求沒有上下文的關系;
3,每次執行的結果都是獨立的,它執行的結果和情況與上前面的請求和之後的請求沒有直接的關系,它不會受前面的請求應答的影響,也不會對後面的請求應答產生影響;
4,服務器沒有保持客戶端的狀態,客戶端每次需要自己將狀態帶到服務區端;
實現狀態保持有兩種方式;
1,在客戶端設置cookie,在每次發送請求的時候將cookie帶給服務器端;
2,在服務器端設置session,每次客戶福安發送來請求之後,將客戶端的cookie與session做做對比;(所有說session是依賴於cookie的,cookie可以單獨存在session不可以獨立存在);
1 #! /usr/bin/env python 2 # *-* coding: utf-8 *-* 3 from datetime import timedelta 4 from flask import Flask 5 from flask import session 6 7 app = Flask(__name__) 8 app.config["SECRET_KEY"] = "abcdefg" 9 10 11 # app.secret_key["SECRET_KEY"] = "abcsefght" 12 13 @app.route(‘/index‘) 14 def index(): 15 user_name = session.get("user_name") 16 user_id = session.get("user_id") 17 return "%s---%s" % (user_name, user_id) 18 19 20 @app.route("/login") 21 def login(): 22 session.permanent = True 23 app.permanent_session_lifetime = timedelta(second=10) 24 session["user_name"] = "xiaomingh" 25 session["user_id"] = "1" 26 return "session設置成功" 27 28 29 @app.route("/logout") 30 def logout(): 31 session.pop("user_name", None) 32 session.pop("user_id", None) 33 return "session刪除刪除成功" 34 35 36 if __name__ == ‘__main__‘: 37 app.run(debug=True)session的設置
請求上下文(request context)
思考:在視圖函數中,如何取到當前請求的相關數據?比如:請求地址,請求方式,cookie等等
在 flask 中,可以直接在視圖函數中使用 request 這個對象進行獲取相關數據,而 request 就是請求上下文的對象,保存了當前本次請求的相關數據,請求上下文對象有:request、session
- request
- 封裝了HTTP請求的內容,針對的是http請求。舉例:user = request.args.get(‘user‘),獲取的是get請求的參數。
- session
- 用來記錄請求會話中的信息,針對的是用戶信息。舉例:session[‘name‘] = user.id,可以記錄用戶信息。還可以通過session.get(‘name‘)獲取用戶信息。
應用上下文(application context)
它的字面意思是 應用上下文,但它不是一直存在的,它只是request context 中的一個對 app 的代理(人),所謂local proxy。它的作用主要是幫助 request 獲取當前的應用,它是伴 request 而生,隨 request 而滅的。
應用上下文對象有:current_app,g
current_app
應用程序上下文,用於存儲應用程序中的變量,可以通過current_app.name打印當前app的名稱,也可以在current_app中存儲一些變量,例如:
- 應用的啟動腳本是哪個文件,啟動時指定了哪些參數
- 加載了哪些配置文件,導入了哪些配置
- 連了哪個數據庫
- 有哪些public的工具類、常量
- 應用跑再哪個機器上,IP多少,內存多大
current_app.name
current_app.test_value=‘value‘
g變量
g 作為 flask 程序全局的一個臨時變量,充當者中間媒介的作用,我們可以通過它傳遞一些數據,g 保存的是當前請求的全局變量,不同的請求會有不同的全局變量,通過不同的thread id區別
g.name=‘abc‘
註意:不同的請求,會有不同的全局變量
flask_script
1 #! /usr/bin/env python 2 # *-* coding: utf-8 *-* 3 4 5 from flask import Flask 6 # 請求上下文的變量 7 from flask import request, make_response 8 # 運用上下文的變量 9 from flask_script import Manager 10 from flask import current_app 11 from flask import g 12 13 app = Flask(__name__) 14 app.debug = True 15 manager = Manager(app) 16 17 18 @app.route(‘/‘) 19 def hello_world(): 20 # 類似於一個全局變量的東西 21 print(current_app.config.get("DEBUG")) 22 return ‘Hello World!‘ 23 24 25 if __name__ == ‘__main__‘: 26 manager.run() 27 # app.run(debug=True)View Code
通過使用Flask-Script擴展,我們可以在Flask服務器啟動的時候,通過命令行的方式傳入參數。而不僅僅通過app.run()方法中傳參,比如我們可以通過:
python hello.py runserver -host ip地址
flask內容學習第二天