1. 程式人生 > >Flask自帶的常用組件介紹

Flask自帶的常用組件介紹

介紹 __main__ pda sin 文件中 blog 標簽 -1 ttr

Flask的優點是靈活小巧,三行代碼即可運行一個web服務器,但基於Flask構建的功能並不比Django弱,關鍵就就是除了flask自帶的基礎功能外,還有豐富的組件進行支持,本文先對常用的自帶組件進行簡單的介紹。測試的Flask版本是0.12。

Flask自帶組件

在構建Flask應用導入的時候,通常是from flask import Flask的方式開始的,說明flask這個python package裏面應該還藏了不少好東西,從源碼來看看:

from werkzeug.exceptions import abort
from werkzeug.utils import redirect
from jinja2 import Markup, escape

from .app import Flask, Request, Response
from .config import Config
from .helpers import url_for, flash, send_file, send_from_directory,     get_flashed_messages, get_template_attribute, make_response, safe_join,     stream_with_context
from .globals import current_app, g, request, session, _request_ctx_stack,     _app_ctx_stack
from .ctx import has_request_context, has_app_context,     after_this_request, copy_current_request_context
from .blueprints import Blueprint
from .templating import render_template, render_template_string

# the signals
from .signals import signals_available, template_rendered, request_started,     request_finished, got_request_exception, request_tearing_down,     appcontext_tearing_down, appcontext_pushed,     appcontext_popped, message_flashed, before_render_template

# We‘re not exposing the actual json module but a convenient wrapper around
# it.
from . import json

# This was the only thing that Flask used to export at one point and it had
# a more generic name.
jsonify = json.jsonify

# backwards compat, goes away in 1.0
from .sessions import SecureCookieSession as Session
json_available = True

Flask自帶組件基本上都在這裏了,我們一一來分析這些組件的功能及基本的用法。

  • Flask
    Flask應用的主類,在源碼分析中提到,不再贅述。這裏給一個Flask應用的經典樣例,請務必註意下面的代碼都是在此樣例基礎上進行拓展的
#示例-1
from flask import Flask

app = Flask(__name__)

@app.route(‘/‘)
def hello_world():
    return ‘Hello World!‘

if __name__ == ‘__main__‘:
    app.run()
  • render_template:

    def render_template(template_name_or_list, **context)

template_name_or_list參數是模板名稱,context參數接受模板中已經定義的變量值。
Jinja是Flask的模板引擎,提供對HTML頁面的數據渲染,render_template是Flask中調用template目錄的html模板並渲染數據。代碼示例:

#示例-2
from flask import render_template

@app.route("/")
def index():
    name="He Kejun"
    return render_template("index.html",name=name)

上述的代碼中調用了/template/index.html

模板,並將“name: He Kejun”這一數據渲染進該模板其可以直接通過Hello, {{name}}的方式顯示‘Hello, He Kejun‘

  • session
    flask的session機制,Flask從服務器通過瀏覽器的cookie保存信息,該信息通過應用的秘鑰進行加密確保數據安全。session在用戶身份認證和數據共享提供較好的幫助。樣例:
#示例-3
from flask import session
app.config["SECRET_KEY"]="YOU CAN NOT GUESS ME" #加密的秘鑰,建議放在配置文件中

@app.route("/")
def index():
    session["name"]="kejun"
    return "hello,world"

@app.route("/name")
def name():
    return session["name"]

首先訪問http://127.0.0.1:5000 生成用戶名,查看瀏覽器的cookie可以看到session已經寫入了,這時候再訪問http://127.0.0.1:5000/name就可以看到名字了,在兩個HTTP請求之間共享了{name: kejun}這個數據。
技術分享
技術分享

  • url_for

    def url_for(endpoint, **values):

根據已經定義好的view函數來創建URL到指定的endpoint,Flask的endpoint可以理解為Restful框架中資源。輸入的endpoint是函數名,values是關鍵字參數,每個關鍵字參數對應URL規則的變量部分,未知變量部分被插入到URL中作查詢參數,具體的樣例,我使用了官網的樣例

#示例-4
from flask import url_for

@app.route("/")
def index(): pass

@app.route("/login")
def login(): pass


@app.route("/user/<username>")
def profile(username):pass

with app.test_request_context():
    print(url_for("index))  #/
    print(url_for("login"))  #/login
    print(url_for("login",next="/"))  #/login?next=/
    print(url_for("profile,username="kejun"))  @/user/kejun
  • redirect

    def redirect(location, code=302, Response=None):

參數location是跳轉的目標位置,code是HTTP響應碼默認是302(臨時移動),也可以設置為301(永久移動,即所請求的文檔在別處),303(參見其他信息),305(使用代理),不可以是300(多重選擇),304(未修正更新)。
redirect的作用是重定向,設置響應並跳轉到指定的位置。在Flask中通常與url_for這個功能一起使用。應用實例:

#示例-5
from flask import redirect

@app.route("/")
@app.route("/index")
def index():
   return redirect(url_for("blog"))

@app.route("/blog")
def blog():  pass

在示例-5中,我們可以將一些用戶可能會訪問的鏈接重定向到博客主頁上。

  • flash

    def flash(message, category=‘message‘):

參數message是消息內容,category是消息類型,方便前端過濾。
Web設計中提供用戶的友好性是及時將反饋提供給用戶。消息閃現Flash提供了一個非常簡單的機制。

#示例-6-1
from flask import flash

def print_message():
    flash("This is a message","message")
    return "Message Page"

def print_error()
    flash("This is a error","error")
    return "Error Page"  

在前端,我們可以這樣定義HTML頁面從而顯示內容

#示例-6-2
{% with msgs = get_flashed_messages(category_filter=["message"]) %}
    {% if msgs %}
        {% for msg in msgs %}
            <p>{{msg}}</p>
        {% endfor %}
    {% endif %}
{% endwith %}
{% with errors= get_flashed_messages(category_filter=["error"]) %}
    {% iferrors%}
         {% for errorinerrors%}
               <p>{{error}}</p>
         {% endfor %}
    {% endif %}
{% endwith %}
  • make_response

    def make_response(*args):

Flask會自動將view函數返回的轉換成響應對象,除此之外,你可以通過調用make_response

#示例-7
from flask import make_response

def index():
      return render_template(‘index.html‘, foo=42)

def index():
       response = make_response(render_template(‘index.html‘, foo=42))
       resp.set_cookie("am_i_handsome","yes") #設置cookie
       return response

在上述的示例中,通過make_response,還可以定制cookie。也就是說,通過make_response你可以個性化定制返回的響應對象。

  • jsonify
    對於數據進行json轉化,應用於通過ajax方式訪問時需要返回json數據。
#示例-8
from flask importjsonify

@app.route("/update_user_name",methods=[‘GET‘, ‘POST‘])
def update_user_name():
    ip=request.headers.get(‘X-Real-Ip‘, request.remote_addr)
    user_name=request.args.get(‘new_user_name‘,"",type=str)
    if user_name:
        if set_user_name(ip,user_name):
            return jsonify(return_code="1")
    return jsonify(return_code="0")
  • blueprint
    blueprint藍圖是flask自帶的一種拓展已有應用結構的方式,這是Flask在中大型Web應用中的一種框架設計。藍圖把把功能類似或者同一模塊下的視圖函數組合在一起,基於藍圖,我們可以把Flask應用拆分成不同的組件。每個藍圖都可以自定義自己的模板文件目錄和靜態目錄。定義好的藍圖目錄可以通過註冊的方式加入Flask應用中。代碼示例如下:
#示例-9-1
from flask import Blueprint

example=Blueprint(‘example‘,__name__,template_folder=‘templates/example‘,static_folder=‘static/example‘,url_prefix=‘/example‘)

#藍圖example下的視圖函數
@example.route
def index():
    return render_template("index.html")

一個藍圖就是一個模塊,上述的example藍圖創建好後,需要註冊到Flask應用中,樣例代碼如下:

示例-9-2
from flask import Flask
from yourapplication.examples import example

app = Flask(__name__)
app.register_blueprint(example)

本文之前介紹了url_for的使用方法,在藍圖中使用url_for定位視圖函數需要增加藍圖名稱,如定位到上述index視圖函數url_for(‘example.index‘)

  • request
    Flask構建了一個與請求相關的全局變量,在所有的視圖函數及模板中都可以訪問該對象。應用示例如下:
#示例-10
from flask import request
def get_user_ip():
    ip=request.headers.get(‘X-Real-Ip‘, request.remote_addr)
    return "Request ip address is {0}".format(ip)
  • abort
    abort是Flask中Abort類的一個實例,通常采用abort(error_code)的方式進行調用。abort的狀態碼最好是自己實現的錯誤定義,如示例-11所示。
  • g
    Flask中的全局變量g,可以為特定請求臨時存儲任何需要的數據並且是線程安全的,當請求結束時,這個對象會被銷毀,下一個新的請求到來時又會產升一個新的g。
#示例-11
from flask import g,session,abort,render_template
@app.before_request
def before_request():
    if ‘user_name‘ in session:
        g.user=User.query.get(session[‘user_name‘])

@app.route(‘/admin‘)
def admin():
    if g.user is None:
        abort(404)
    return render_template(‘admin.html‘)

@app.errorhandler(404):
def page_not_found():
    return render_template("404.html"),404
  • send_from_directory

    def send_from_directory(directory, filename, **options):

參數directory是文件所在目錄,filename是文件名稱,options參數是send_file的傳入參數,options可選的參數包括 mimetype、as_attachment、attachment_filename、add_etags、cache_timeout、conditional。
send_from_directory可以認為send_file上加了一層殼子,判斷了文件路徑及文件名,然後交由send_file處理,實際上將文件內容發給瀏覽器,所以它一個重要的應用場景是支持文件下載。
對於文件下載,媒體數據流傳輸的可以再研究一下send_filestream_with_context這兩個功能,也非常好用。
示例代碼為:

#示例-11
from flask import send_from_directory

@app.route(‘/getfile‘, methods=[‘GET‘])
def download_file():
    return send_from_directory(r"D:\Workspace\flask_source", "aa.txt", as_attachment=True)
  • Markup

    class Markup(text_type):

將輸入文本text_type標記為安全,不需要進行轉移。
如果將HTML作為變量通過Jinjia模板的方式作為變量插入頁面中,Flask會自動嘗試對HTML進行轉義。這是必要的安全措施,確保惡意用戶通過提交一段惡意代碼並顯示在頁面中,從而讓其他用戶的瀏覽器進行執行。Flask同時提供兩種方法來對安全的HTML不轉義直接顯示:一個是利用Markup類,二是利用Jinjia關鍵字safe。示例代碼為:

示例-12
from flask import Markup
@app.route("/")
def index():
    return Markup(‘Hello %s!‘) % ‘<strong>kejun</strong>‘#顯示strong標簽

@app.route("/1")
def index1():
    return ‘Hello %s!‘ % ‘<strong>kejun</strong>‘#將strong標簽轉移成顯示
  • current_app
    應用上下文對象,官方文檔有詳細的介紹,

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

Flask自帶的常用組件介紹