flask.__init__.py
和核心組件首先看看一個簡單的示例。使用 Flask ,一般是從 flask 模塊導入 Flask 、 request 等等組件。一個簡單的示例以下:html
from flask import Flask app = Flask(__name__) app.config.update(DEBUG=True) @app.route('/') @app.route('/index') def index(): return '<h1>Hello, world!</h1>' if __name__ == '__main__': app.run()
這個簡單示例只使用到 Flask 中的核心 Flask 對象,以及 Flask 的 route 機制,就能簡單地提供一個顯示 Hello, world!
字符串的 index 頁面。其它更加複雜的結構和使用模式,都會基於相似的簡單例子進行擴展,以知足一些特定場景的要求。web
flask.__init__.py
除了 Flask 類,在 flask 模塊裏面還包含了其它 Flask 裏的核心組件,打開這個源文件,可看到它裏面包括:redis
abort數據庫
從 werkzeug.exceptions
導入,調用時直接拋出異常。它的本質是 werkzeug.exceptions
裏面的 Aborter() 對象。編程
Aborter 使用工廠模式。其內部使用一個 dict 類型的 mapping
成員變量來保存從 http 狀態碼到 werkzeug.exceptions
中定義的全部異常類之間的一個映射,而後經過一個 magic 方法 __call__
建立並拋出異常。json
全部的異常的基類爲 HTTPException
。它包含了兩個基本的成員,code
和 description
,分別表示停止時的 http 狀態碼和要返回給用戶的信息。flask
異常類定義完後,經過一個函數 _find_exceptions
把全部在這裏定義的異常類,放入到 default_exceptions
這個 dict 全局變量中。Abort 的初始化函數默認用 default_exceptions
做爲 mapping
的值。瀏覽器
abort
支持的狀態碼包括 400 / 401 / 403 / 404 / 405 / 406 / 408 / 409 / 410 / 411 / 412 / 413 / 414 / 415 / 416 / 417 / 418 / 422 / 428 / 429 / 429 / 431 / 500 / 501 / 502 / 503 / 504/ 505 。安全
使用示例:服務器
@app.route('/_404') def _404() abort(404, 'Oops, 404.')
redirect
從 werkzeug.utils
導入的重定向函數,一般與 url_for
結合使用。
redirect
生成一個 Response
對象,默認以 302 狀態碼返回響應。其響應的模板內容爲(其中 escape 爲 URL 轉義函數):
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n' '<title>Redirecting...</title>\n' '<h1>Redirecting...</h1>\n' '<p>You should be redirected automatically to target URL: ' '<a href="%s">%s</a>. If not click the link.' % (escape(location), display_location), code, mimetype='text/html'
可見,當瀏覽器不支持 302 狀態碼自動重定向時,可經過點擊響應的 html 中的連接進行跳轉。
使用示例:
@app.route('/_redirect') def _redirect() return redirect(url_for('.index'))
Markup 和 escape
這兩個都是從 Jinja2
中導入,實際由另一個模塊 markupsafe
實現。 Markup
在 markupsafe
模塊的 __init__.py
中,是對文本的一個封裝,對字符串進行安全的轉義,從而能方便地使用到 html 和 xml 中。 Markup
的實現過程當中,使用到 escape
函數幫助轉義。
escape
的實現其實很簡單,就是把 html 中的預留字符轉換爲實體,代碼以下:
return Markup(text_type(s) .replace('&', '&') .replace('>', '>') .replace('<', '<') .replace("'", ''') .replace('"', '"') )
就是把 & > < ' "
這幾個字符轉換爲實體。
使用示例:
Markup('<h1>%s<h1>') % '<h1>Hello, world!<h1>' # 結果爲 Markup('<h1><h1>Hello, world!<h1><h1>')
Flask Request Response
這 3 個類從 flask.app
中導入(使用了當前相對位置導入 from .app import ...
)。
Flask
是整個 Flask 框架的核心類,它實現了 WSGI 的應用接口,提供路由、模板解析、日誌、異常管理等等核心功能。
Request
和 Response
分別是對請求和響應的數據的包裝,實際的代碼在 flask.wrappers
中。它們繼承 werkzeug.wrappers
裏面的請求和響應類,根據 Flask 的設計概念的須要進行了擴展。
後續深刻分析這 3 個類
使用示例:
from flask import Flask, Response, request app = Flask(__name__) @app.route('/') def index(): method = request.method return Response('Request method: %s' % method) if __name__ == '__main__': app.run()
輔助函數 url_for
flash
send_file
, send_from_directory
等
這堆輔助函數從 flask.helpers
中導入,包括:
url_for, flash, send_file, send_from_directory, get_flashed_messages, get_template_attribute, make_response, safe_join, stream_with_context
後續深刻分析這些函數
上下文全局對象代理 current_app
g
request
等
這些對象從 flask.globals
導入,在當前上下文環境中起做用,包括:
current_app, g, request, session, _request_ctx_stack, _app_ctx_stack
上下文模式是 web 框架中常常會使用到的模式,它表示當前會話、請求、應用的執行環境,是當前代碼執行時所能使用到的變量、函數等等。不一樣的用戶一般使用不一樣的上下文環境,經過相互隔離上下文環境提供必定的安全特性。上下文還與特定的實現技術有關,線程、協程會使用不一樣的實現方法,有時在不一樣的系統中會有須要注意的細節。
在實踐中遇到的一些問題,特別是與 Flask 擴展有關的問題,不少是與上下文不對有關。
注意,current_app
g
request
session
均是 LocalProxy
,在運行時經過查找函數加載真正的對象。
後續深刻分析 flask.globals
。
上下文處理 has_request_context
has_app_context
after_this_request
copy_current_request_context
這些函數和組件從 flask.ctx
導入,輔助處理上下文。
在 flask.ctx
中還定義了 ApplcaitonContext
和 RequestContext
兩個上下文類。
RequestContext
包含請求時的信息,在請求開始時建立,在請求結束後清理。
ApplicationContext
包含應用的信息,綁定到當前的線程和協程上。當 RequestContext
發現沒有 ApplicationContext
時,也會自動隱式建立一個(在 RequestContext.push()
中)。
後續深刻分析。
Module 和 Blueprint
分別從 flask.module
和 flask.blueprints
導入,是 Flask 的擴展機制。根據 Module
中的註釋,這種方式已通過時,被 Blueprint
取代。
.. versionchanged:: 0.7 Modules were deprecated in favor for blueprints.
Blueprint
是 Flask 中的主要模塊化擴展方法。在編寫大規模的應用時,可劃分功能爲多個 Blueprint
,每一個 Blueprint
完成特定任務。
使用示例:
task_bp = Blueprint('task') app.register_blueprint(task_bp, url_prefix='/task')
後續深刻分析。
視圖渲染 render_template
render_template_string
這兩個函數從 flask.templating
導入,完成模板的渲染工做。
使用示例:
# 模板文件 templates/index.html <h1>{{ content }}</h1> # 視圖渲染代碼 @app.route('/') def index(): return render_template('index.html', content='Hello, world!')
後續深刻分析。
內部信號 signals_available
template_rendered
request_started
等等
Flask 提供信號機制,當某些操做發生時,經過信號方式通知其它代碼,方便在這些操做發生時進行進一步處理。
現有的信號包括:
signals_available, template_rendered, request_started, request_finished, got_request_exception, request_tearing_down, appcontext_tearing_down, appcontext_pushed, appcontext_popped, message_flashed
信號機制使用 blinker ,若是要自定義信號,須要額外安裝這個模塊。
json 支持 jsonify
經過 json 方式進行響應。
使用示例:
return jsonify([1,2,3,4])
Session
Session 對象,實際類型爲 'flask.sessions.SecureCookieSession',須要結合 SecureCookieSessionInterface
一塊兒使用。
它能夠用來定製 Flask 的 Session 保存方式,可放入到數據庫或者 redis 裏面,實現跨服務器的 session 共享。session 共享後,可經過服務器集羣提高整個應用的訪問處理能力。
官方文檔有一個使用 redis 實現的 server-side session http://flask.pocoo.org/snippets/75/ 。
後續深刻分析。
以上已列出 Flask 裏面的關鍵組件和概念,若是掌握這部分的概念,則使用 Flask 的過程當中所遇到的問題基本能本身動手調試和解決。剛接觸像上下文、信號機制、server-side session 等概念時會存在疑惑,這些概念須要理解源代碼後,實際編程使用的過程當中會慢慢熟悉。
後續的文章圍繞上述概念展開,並探索 Flask 如何設計和實現這些概念,在整個實現過程當中學習 Flask 的優秀設計。