Inside Flask - flask.__init__.py 和核心組件

Inside Flask - 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 。它包含了兩個基本的成員,codedescription,分別表示停止時的 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 實現。 Markupmarkupsafe模塊的 __init__.py 中,是對文本的一個封裝,對字符串進行安全的轉義,從而能方便地使用到 html 和 xml 中。 Markup 的實現過程當中,使用到 escape 函數幫助轉義。

    escape 的實現其實很簡單,就是把 html 中的預留字符轉換爲實體,代碼以下:

    return Markup(text_type(s)
          .replace('&', '&amp;')
          .replace('>', '&gt;')
          .replace('<', '&lt;')
          .replace("'", '&#39;')
          .replace('"', '&#34;')
      )

    就是把 & > < ' " 這幾個字符轉換爲實體。

    使用示例:

    Markup('<h1>%s<h1>') % '<h1>Hello, world!<h1>'
      # 結果爲 Markup('<h1>&lt;h1&gt;Hello, world!&lt;h1&gt;<h1>')
  • Flask Request Response

    這 3 個類從 flask.app 中導入(使用了當前相對位置導入 from .app import ...)。

    Flask 是整個 Flask 框架的核心類,它實現了 WSGI 的應用接口,提供路由、模板解析、日誌、異常管理等等核心功能。

    RequestResponse 分別是對請求和響應的數據的包裝,實際的代碼在 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 中還定義了 ApplcaitonContextRequestContext 兩個上下文類。

    RequestContext 包含請求時的信息,在請求開始時建立,在請求結束後清理。

    ApplicationContext 包含應用的信息,綁定到當前的線程和協程上。當 RequestContext 發現沒有 ApplicationContext 時,也會自動隱式建立一個(在 RequestContext.push() 中)。

    後續深刻分析。

  • Module 和 Blueprint

    分別從 flask.moduleflask.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 的優秀設計。

相關文章
相關標籤/搜索