摘要:的上下文對象有兩種上下文,分別是請求上下文請求的對象,封裝了請求的內容,生命周期請求處理完就結束了根據請求中的,重新載入該訪問者相關的會話信息應用上下文處理請求時用作臨時存儲的對象。
Werkzeugs 是 Flask 的底層WSGI庫。什么是WSGI?
一段簡單的app:
def dispath_request(self, request): return Response("Hello World!") def wsgi_app(self, environ, start_response): request = Request(environ) response = self.dispath_request(request) return response(environ, start_response)
environ: 包含全部的HTTP請求信息的字典,由WSGI Server解包 HTTP 請求生成。
start_response:一個WSGI Server 提供的函數,調用可以返回相應的狀態嗎和HTTP報文頭,函數在返回前必須調用一次。
Flask有兩種Context(上下文),分別是
RequestContext 請求上下文;
Request 請求的對象,封裝了Http請求(environ)的內容,生命周期請求處理完就結束了;
Session 根據請求中的cookie,重新載入該訪問者相關的會話信息;
AppContext 應用上下文;
g 處理請求時用作臨時存儲的對象。每次請求都會重設這個變量, 生命周期請求處理完就結束了;
current_app 當前激活程序的程序實例,只要當前程序還在運行就不會失效。
flask 處理請求和響應的流程:在 "flask/globals.py" 代碼中:
# context locals _request_ctx_stack = LocalStack() # LocalStack 是由werkzeug提供的棧結構類提供了push、pop等方法 # 并且Local對象是werkzeug開發的類似 thinking.local(用于隔離不同線程間的全局變量) 對象,實現了在同一個協程中數據的隔離和全局性,具體怎么實現看源代碼,暫時沒看明白 _app_ctx_stack = LocalStack() current_app = LocalProxy(_find_app) # partial(_lookup_req_object, "request") 總是返回 LocalStack 棧頂對象的 request 屬性 # LocalProxy 用于代理Local對象和LocalStack對象,至于為什么使用代理。。 request = LocalProxy(partial(_lookup_req_object, "request")) session = LocalProxy(partial(_lookup_req_object, "session")) g = LocalProxy(partial(_lookup_app_object, "g"))
flask local https://www.jianshu.com/p/3f38b777a621
為什么要使用 LocalProxy 而不直接使用 Local 和 LocalStack
# AppContext 應用上下文 # # 在flask/app.py下: # def app_context(self): # self 就是app對象 return AppContext(self) # # 在 `flask/ctx.py` 代碼中 # class AppContext(object): def __init__(self, app): self.app = app self.url_adapter = app.create_url_adapter(None) self.g = app.app_ctx_globals_class() # Like request context, app contexts can be pushed multiple times # but there a basic "refcount" is enough to track them. self._refcnt = 0 def push(self): # 這個方法就是把應用上下文push到LocalStack,AppContext類有__enter__方法 """Binds the app context to the current context.""" self._refcnt += 1 if hasattr(sys, "exc_clear"): sys.exc_clear() _app_ctx_stack.push(self) appcontext_pushed.send(self.app) # # 在 flask/cli.py 中有 # def with_appcontext(f): @click.pass_context def decorator(__ctx, *args, **kwargs): # decorator 被裝飾器后 _ctx 參數是 threading 的 local() 對象 with __ctx.ensure_object(ScriptInfo).load_app().app_context(): # 在這里就把 應用上下文push到了LocalStack return __ctx.invoke(f, *args, **kwargs) return update_wrapper(decorator, f) # RequestContext 請求上下文 # #在flask/app.py下 # def request_context(self, environ): # 一次請求的環境變量 return RequestContext(self, environ) # # 在flask/ctx.py下: # class RequestContext(object): def __init__(self, app, environ, request=None): self.app = app if request is None: request = app.request_class(environ) self.request = request self.url_adapter = app.create_url_adapter(self.request) self.flashes = None self.session = None ... ... def push(self): ... _request_ctx_stack.push(self) # #在flask/app.py下 # def wsgi_app(self, environ, start_response): # 這里類似上面的那小段簡單 Werkzeugs app ctx = self.request_context(environ) error = None try: try: ctx.push() response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: error = sys.exc_info()[1] raise return response(environ, start_response) finally: if self.should_ignore_error(error): error = None ctx.auto_pop(error)到此從 AppContext 到 RequestContext 梳理完 app.py 源碼中有這么幾個裝飾器:
before_request(self, f) # 注冊一個在請求到達前要執行的函數
before_first_request(self, f) # 注冊在整個應用實例第一個請求到達前要執行的函數
after_request(self, f) # 注冊一個在請求處理后的函數
teardown_request(self, f) # 注冊在請求上下文棧彈出后要執行的函數
teardown_appcontext(self, f) # 注冊在應用上下文結束時要執行的函數
context_processor(self, f) # 向模板上下文中注入變量和方法,這個f必須返回一個字典, 在渲染的模板中使用
url_defaults(self, f) # 為應用程序中的所有視圖函數 注冊URL值預處理器函數。 這些函數將在:before_request函數之前調用。
url_value_preprocessor(self, f) # 注冊一個 ‘在請求的url匹配后視圖函數執行前,把環境中的某些變量換個位置存儲的’ 函數
# url_defaults(self, f) 和 url_value_preprocessor(self, f) 的使用 from flask import Blueprint, render_template profile = Blueprint("profile", __name__, url_prefix="/方法:") @profile.url_defaults def add_user_url_slug(endpoint, values): values.setdefault("user_url_slug", g.user_url_slug) @profile.url_value_preprocessor def pull_user_url_slug(endpoint, values): g.user_url_slug = values.pop("user_url_slug") query = User.query.filter_by(url_slug=g.user_url_slug) g.profile_owner = query.first_or_404() @profile.route("/") def timeline(): return render_template("profile/timeline.html") @profile.route("/photos") def photos(): return render_template("profile/photos.html") @profile.route("/about") def about(): return render_template("profile/about.html")
dispatch_request(self): 匹配路由,返回視圖函數或者錯誤處理函數的返回值,并且檢測是否為option請求,如果是則構造默認的 ‘options response’ 響應。構造過程首先是 Request uri 所支持的方法集(get、post、等),然后更新 Response 中 allow 屬性(set類型),最后返回Response對象,若不是option請求則執行視圖函數;
make_response(self, rv): rv是視圖函數的返回值,在python3中,rv可以使一個元組(body、status、headers)、Response類對象、 或者一個返回Response類對象的回調函數。這個函數的功能就是把視圖函數返回的 status headers 綁定到 Response;
create_url_adapter(self, request):url_map 適配器。對werkzeug的Map的bind和bind_to_environ兩個方法進行了封裝。bind: 綁定一個主機地址,并返回MapAdapter對象 ; bind_to_environ( 將MAP綁定到WSGI環境中,并返回MapAdapter對象(參數script_name在進行重定向時會用到);
try_trigger_before_first_request_functions(self):在該實例第一個請求到達時把當前線程加鎖,然后依次執行被 before_first_request(self, f)裝飾過得函數,然后釋放鎖并把_got_first_request置為True,再次就直接return;
preprocess_request(self) :該函數就是執行被url_value_preprocessor 和 before_request裝飾過的函數;
full_dispatch_request(self): 先執行try_trigger_before_first_request_functions,然后執行preprocess_request,若before_request中的函數有返回值則為其構造Response,然后跳過排在此函數后邊的函數包括視圖函數,若before_request的函數都返回的None或沒有函數就執行 dispatch_request(self);
inject_url_defaults(self, error, endpoint, values): 執行被"url_defaults" 裝飾的函數
process_response(self, response): 同preprocess_request(self)
通過查看源碼了解到的幾個工具:click 包 把python代碼打包成命令行工具
mimetypes 包 查看文件類型
itsdangerous 簽名 序列化字符串
參考資料:
Flask的核心機制!關于請求處理流程和上下文
Werkzeug(Flask)之Local、LocalStack和LocalProxy
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/45028.html
摘要:我們的論壇項目就使用了該框架。此外,麥子學院也有一個入門視頻教程,一共小時的視頻教程,涵蓋開發的方方面面,包括環境的搭建,語法介紹,項目結構的組織,全球化,單元測試等內容。博客地址更多閱讀的機制三個框架的對比 前面兩篇文章中我們已經了解 Web(HTTP)服務器,Web應用程序,Web框架,WSGI這些 Python Web 開發中的概念。我們知道,Web框架通過將不同Web應用程序中...
摘要:注模板包含不存在此問題。在模板中,使用過濾器顯式地標記一個字符串為安全的臨時地完全禁用自動轉義系統。通過在聲明中直接添加或,當前的上下文可以傳遞到模板,而且不會自動禁用緩存。 官網:http://jinja.pocoo.org/docs/dev/中文文檔:http://docs.jinkan.org/docs/j...當前版本2.8 安裝:pip install Jinja2Flask...
摘要:通過的核心特性,函數可實現這種效果僅調用函數并不能把消息顯示出來,程序使用的模板要渲染這些消息。注意在模板中使用循環是因為在之前的請求循環中每次調用函數時都會生成一個消息,所以可能有多個消息在排隊等待顯示。 五、表單 1、Flask-WTF 擴展 Flask-WTF 及其依賴可使用 pip 安裝: (venv) $ pip install flask-wtf 2、跨站請求偽造保護 【設...
閱讀 1844·2023-04-25 14:49
閱讀 3123·2021-09-30 09:47
閱讀 3111·2021-09-06 15:00
閱讀 2231·2019-08-30 13:16
閱讀 1443·2019-08-30 10:48
閱讀 2674·2019-08-29 15:11
閱讀 1294·2019-08-26 14:06
閱讀 1670·2019-08-26 13:30