1. 對於django來講,內部組件特別多,自身功能強大,有點大而全,而flask,內置組件不多,可是它的第三方組件不少, 擴展性強,有點短小精悍,而它們之間也有類似之處, 由於它們兩個框架都沒有寫sockte,都是基於wsgi協議作的,在此以外,flask框架中的上下文管理較爲耀眼。 相同點:它們兩個框架都沒有寫sockte,都是基於wsgi協議作的 請求相關數據傳遞的方式不一樣:django:經過傳遞request參數取值 flask: request的模塊 組件不一樣:django組件多 flask組件少,第三方組件豐富 注意: 使用上下文管理機制 -threading.local()/greenlet.get_current()?---》Local的做用? 做用:爲每一個線/攜程程建立一個獨立的空間,使得線程對本身空間中的數據進行操做(數據隔離)。 應用:DBUtils中爲每一個線程建立一個數據庫連接時使用 -如何獲取一個線程的惟一標記:threading.get_ident() -再次根據線程惟一標記,設置一個大內存字典的key,值就是線程空間中的數據 -DBUtils線程池的模式也是爲每一個線程建立一個連接 -SQLAlchemy的create_engine也會建立線程池以供使用 2. session 兩個Local和LocalStack分別對應ctx和app_ctx 請求上下文管理(ctx):request,session 應用上下文管理(ap_ctx) - 請求到來以後wsgi會觸發__call__方法,由__call__方法再次調用wsgi_app方法 - 在wsgi_app方法中: - 首先將 請求相關+空session 封裝到一個RequestContext對象中,即:ctx。 - 將ctx交給LocalStack對象,再由LocalStack將ctx添加到Local中,Local大字典結構: __storage__ = { 1231:{stack:[ctx] } } - 根據請求中的cookie中提取名稱爲session_id對應的值,對cookie進行加密+反序列化,再次賦值給ctx中的session -> LocalStack獲取Local中的數據後,視圖函數經過LocalProxy,獲取LocalStack中相對應的值 - 增刪改查 - 把session中的數據再次寫入到cookie中。 - 將ctx刪除 - 結果返回給用戶瀏覽器 - 斷開socket鏈接 3. 問題: 爲何要把 ctx=request/session app_ctx = app/g 分開? 答:編寫離線腳本時,須要配置文件,而配置文件存放在app中,並不須要請求相關數據 因此把app和請求相關的數據分開。若是隻是須要g傳遞數據,則在g的生命週期中徹底夠用 在web runtime時,棧中永遠只有一個ctx,或者app_ctx; 在使用離線腳本時,則可能存在多個,可是數據並不會混雜,經過with語句和top取值(-1)能夠分層次獲取 4. Flask中g的生命週期? 在請求觸發__call__調用wsgi_app時,生成app_ctx=AppContext(app,g) 在請求結束時app_ctx.pop()結束g 5. g和session同樣嗎? g是在有請求時被建立,請求結束時刪除,下次請求又是一個新的g session會被加密序列化寫入用戶cookie,下次請求解密反序列化就有 6. g和全局變量同樣嗎? 全局變量在程序啓動時只生成一次,有且只有這一個變量 g在請求時被生成,請求結束時被刪除,是臨時可建立變量 7.依賴的wsgi(服務器網關接口): werkzurg 8. 配置文件 能夠設置一個跟Django差很少的settings配置文件,經過app.config.from_object("settings.xxx")路徑, 具體實現是經過importlib模塊和getattr反射找到「字符串路徑」,再引用配置相關信息 9. 路由系統 -基於裝飾器實現的路由系統 -endpoint,反向生成URL,默認函數名 -url_for("函數名" or endpoint)--------注意endpoint反向生成url時有同名, 須要導入import functools -> @functools.wraps(func) 保留原函數的原信息 -functool.partial 偏函數(減小用戶輸入函數參數) -動態路由:@app.route("/index/<int:nid>") 傳遞參數使用 10. 視圖 -基於反射區別method請求 -FBV 路由設置:@app.route("/xxxx") -CBV methods = ["GET",] decorators = ["wrapper"] 路由設置:app.add_url_rule("/xxx", None, UserView.as_view('aaa')) 11. 請求相關 # 請求相關信息 # request.method request.path # request.args request.full_path # request.form request.url # request.values request.files # request.cookies request.headers 12. 響應 響應體: return "字符串" return jsonify({"k1": "v1"}) return render_template("xx.html") return redirect("/xxxx") 定製響應體: -面向對象的封裝 obj = make_response("字符串") obj.headers["k1"] = "v1" obj.set_cookie("key", "value") return obj 設置全局訪問權限: @app.before_request def xxx(): if request.path == '/login': return None if session.get('user'): return None return redirect('/login') 13. 模板渲染 -基本數據類型:能夠執行python語法 -傳入函數: -django, 自動執行 -flask, 須要手動加括號執行 -全局定義函數 @app.template_global() def xx(a1, a2): # {{sb(1,9)}} return a1 + a2 -添加撒選條件 @app.template_filter() def db(a1, a2, a3): # {{ 1|db(2,3) }} return a1 + a2 + a3 -模板繼承跟django差很少 -預約義模塊(不傳值看不見,傳值就啓動) -安全 - 前端: {{u|safe}} - 後端: MarkUp("asdf") 14. 閃現 -在session中存儲一個數據,讀取時經過pop將數據移除,獲取的值返回給用戶 15. 中間件 - call方法何時觸發? - 用戶發起請求時,才執行。 16. 藍圖(blueprint) -目標:給開發者提供目錄結構 其餘: - 自定義模板、靜態文件 - 某一類url添加前綴 - 給一類url添加before_request 17. 特殊裝飾器 -放在列表,循環執行 1. before_request (請求相關) 2. after_request 3. before_first_request 4. template_global (模板相關) 5. template_filter 6. errorhandler (能夠自定義錯誤信息) 18.before_request的執行時機(源碼實現:存放在一個列表)Local執行以後,視圖執行以前 19. threading.local (DBUtils組件建立一個線程池) 20. 爲何導入request,就可使用? 每次執行request.xx方法時,會觸發LocalProxy對象的__getattr__等方法,由方法每次動態的使用 LocalStack去Local中獲取數據。 21.擴展: 1. flask-session 2. DBUtils 其餘地方也可使用 3. wtforms 4. sqlalchemy