Flask基礎(3):session、flash、特殊裝飾器、藍圖、路由正則匹配、上下文管理 & flask-session
阿新 • • 發佈:2018-12-20
Session:
Flask 預設將 session 以加密的形式放到了瀏覽器的 cookie 中 Flask 的 session 就是一個字典,字典有什麼方法 session 就有什麼方法 flask session 原理:當請求剛進來時,flask會讀取cookie中 session(配置檔案中能改這個名稱) 對應的值,將這個值解密並反序列化成為一個字典放入記憶體, 以便檢視函式使用; 在檢視函式中使用時,按照字典的方法使用; 當請求結束時,flask會讀取記憶體中字典的值,進行序列化+加密,然後再寫入到使用者的 cookie 中
flash:
# flash 是 取一次就沒有;基於 session 實現的 # 原理:在 session 中儲存一個數據,讀取時通過 pop 將資料移除,從而達到只能取一次的效果 from flash import get_flashed_messages flash("臨時資料儲存","error") # 存 flash;"error" 表示分類 get_flashed_messages() # 取 flash 中的值;列表的形式; get_flashed_messages(category_filter=["error"]) 表示根據 分類取 flash
特殊裝飾器:(重點)
**1. @app.before_request # 所有請求之前進行的操作;被裝飾的函式沒有 引數 和 返回值;作用類似於 Django 的 process_request 2. @app.template_global() # 給模板用的 3. @app.template_filter() # 給模板用的 **4. @app.after_request # 被裝飾的函式要有 引數 和 返回值;作用類似於 Django 的 process_response @app.after_requestdef test(response): print("after_request") return response # 對於有多個 @app.before_request ,誰先定義誰先執行;對於有多個 @app.after_request ,誰先定義誰後執行;類似於 Django 中介軟體的執行順序 # 對於 before_request,可以在定義自己邏輯時新增返回值,這樣就不會執行後面的 before_request 和 檢視,但還會執行所有的 after_request;這是和 Django(1.10以後版本不一樣的地方) 5. @app.before_first_request # 只有第一次請求才執行 6. @app.errorhandler(錯誤碼) # 報錯的時候執行的函式;可用於定製錯誤資訊(頁面) @app.errorhandler(404) def not_found(arg): # arg 是錯誤資訊 print(arg) return "沒找到"
Blueprint:藍圖
示例目錄:
crm |---crm |--- __init__.py # 例項化 Flask 等等 |---views |---account.py |---user.py |---manage.py # 入口函式
manage.py
from crm import create_app app = create_app() if __name__ == '__main__': app.run() # 執行 Flask 的例項
crm/__init__.py
from flask import Flask from .views.account import ac from .views.user import uc def create_app(): app = Flask(__name__) # @app.before_request # 全域性性的 before_request # def x1(): # print('app.before_request') app.register_blueprint(ac) app.register_blueprint(uc,url_prefix='/api') # 給 uc 這個藍圖的 url 新增一個 字首 return app
crm/views/account.py
from flask import Blueprint,render_template ac = Blueprint('ac',__name__) # 例項化一個藍圖 @ac.before_request # 只給 ac 這個藍圖新增 before_request def x1(): print('app.before_request') @ac.route('/login') def login(): return render_template('login.html') @ac.route('/logout') def logout(): return 'Logout'
crm/views/user.py
from flask import Blueprint uc = Blueprint('uc',__name__) @uc.route('/list') def list(): return 'List' @uc.route('/detail') def detail(): return 'detail'
藍圖的作用:
1. 目錄結構的劃分 2. 路徑加字首 3. 給某些應用(檢視)加裝飾器
路由的正則匹配:
# 1. 先定義一個類: RegexConverter(BaseConverter) # 2. app.url_map.converters["reg"] = RegexConverter # 3. 使用者傳送請求 # 4. 使用自定義正則: @app.route("/index/<reg('\d+'):nid>") def index(nid): print(nid,type(nid) print(url_for('index',nid=987) # 返回生成url時,自動觸發 RegexConverter 的 to_url 方法 # 4. flask內部進行正則匹配 # 5. to_python 方法的返回值會交給檢視函式的引數
上下文管理:
1. request 2. session # 注: Flask 預設將 session 以加密的形式放到了瀏覽器的 cookie 裡面 3. app 4. g
請求--檢視--響應 大致流程:
請求到來時: # ctx = RequestContext(self,environ) # self 是 app物件,environ表示請求相關的原始資料 # ctx.request = Request(environ) # ctx.session = None # 將包含了 request和session 的ctx物件打包放到某個地方(相當於一個大字典;根據執行緒或協程加個唯一標識,放進去的,所以資料相互隔離) { 1232:{ctx:ctx物件}, ... } 檢視函式: from flask import request,session # 上述程式碼背後的過程:根據當前執行緒或者協程的唯一標識,取到 ctx物件,然後取到 request和session 請求結束: 根據當前執行緒的唯一標識,將 大字典 中該執行緒對應的資料移除
上下文管理--request:
# 1. wsgi:初步處理請求 # 2. __call__ 方法 --> wsgi_app 方法 # 3. wsgi_app方法: ctx = RequestContext(session,request) ctx.push() # 4. LocalStack:把 ctx 物件新增到 Local 中 (LocalStack起到一箇中介的作用;檢視函式取值時也是來 LocalStack 中取值,而不能直接去 Local 中取) # 5. Local:為每個執行緒或協程開闢一塊相互隔離的記憶體空間; local物件中有一個 __storage__ 的字典 __storage__ = { 執行緒/協程唯一標識:{"stack":[ctx物件(request和session),]} }
上下文管理--session:
# 通過 LocalStack 獲取 ctx 中的 session,給 session 賦值(從 cookie 中讀取資料,進行解密和反序列化;呼叫 open_session() 方法)
補充:
# Flask 和 Django 對比: 相同點:都是基於 wsgi 協議寫的 最大不同點:request的機制不同:請求相關的資料,對於Django是通過引數傳遞一個一個傳遞過來的;flask是把請求相關的資料放到“一個地方”(大字典),以後就來這裡取對應的資料 # 全域性變數只有在初次載入時執行 # 類中的 __slots__() 的作用:在類外面只有 ()中的屬效能通過 . 獲取到,如: __slots__("name") ,只能獲取到 obj.name
flask-session:
# Flask 第三方元件--flask-session:可將 session 儲存到 redis 中
安裝:
pip install flask-session
使用:
import redis from flask import Flask,request from flask_session import Session # 匯入 flask-session 中的 Session app = Flask(__name__) app.config["SESSION_TYPE"] = "redis" # 3. 由下面的分析可知,配置檔案中應該要先配置好 SESSION_TYPE; 此時 app.session_interface = RedisSessionInterface();RedisSessionInterface 中也有 open_session 和 save_session 這兩個方法 app.config["SESSION_REDIS"] = redis.Redis(host="127.0.0.1",port=6379,password="") # 4. 配置 session 的 Redis # 通過這些操作, session 就會儲存到 redis 中;此時儲存在 瀏覽器中的 cookie 是一個 隨機字串(uuid.uuid4()),當請求到達時 通過這個 cookie(隨機字串)來 redis 中取 session # 1. flask 預設的 session 處理是通過 app.session_interface = SecureCookieSessionInterface() Session(app) # 2. app 經過 Session 例項化之後,app.session_interface = self._get_interface(app) ; session 儲存到哪和 配置檔案中的 "SESSION_TYPE" 有關 pass