flask-quickstart 官方網(wǎng)站翻譯

翻譯的網(wǎng)站
備注 我只會(huì)翻譯一些關(guān)鍵點(diǎn)。太簡(jiǎn)單的就不翻譯了

Quickstart

一個(gè)小程序可能看起來(lái)會(huì)是這樣的

#hello.py
from flask import Flask
app = Flask(__name__)

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

通過(guò)命令行啟動(dòng)程序有兩種方式

# 1.
export FLASK_APP=hello.py
flask run
#2.
export FLASK_APP=hello.py
python -m flask run

如果想讓你的程序成為可訪問(wèn)的公共服務(wù)器

flask run --host=0.0.0.0

如果啟動(dòng)成功你就可以通過(guò) http://127.0.0.1:5000來(lái)看到你的Hello, World!

失敗的原因可能有多種揭朝,有可能是你的flask版本過(guò)低呢簸,也有可能導(dǎo)入的包名無(wú)效褒链,或者你也可以開(kāi)啟Debug模式

export FLASK_DEBUG=1

在這種模式下阻问,flask能夠提供有用的調(diào)試信息昌简,也能夠自動(dòng)監(jiān)聽(tīng)代碼改動(dòng)而重啟服務(wù)器吟逝。
另外帽蝶,不建議你在開(kāi)發(fā)階段,通過(guò)在代碼中使用如下方法啟動(dòng)服務(wù)器。

if __name__ == '__main__':
    app.run()

flask 匹配與生成url的兩個(gè)函數(shù)

@app.route('/user/<username>')
... def profile(username): pass
url_for('profile',username='john deo')

Http(超文本協(xié)議) 傳輸方法

from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        do_the_login()
    else:
        show_the_login_form()

http PUT

PUT與POST類似励稳,但服務(wù)器能通過(guò)覆蓋舊值多次激發(fā)存儲(chǔ)程序佃乘,例如傳輸過(guò)程種程序與服務(wù)器斷開(kāi)連接,PUT能夠在不中斷服務(wù)的情況下安全的接受二次請(qǐng)求驹尼,而POST做不到趣避。

靜態(tài)資源

包括css js 圖片等,flask都會(huì)默認(rèn)在static文件中尋找它們新翎。所以你要使用靜態(tài)文件程帕,首先要建立static文件夾。

獲得靜態(tài)文件的地址可以通過(guò)

url_for('static', filename='style.css')  # static/style.css

Html模版

默認(rèn)的flask從template文件夾中尋找模版地啰,確保它在你的模塊或包中
flask 封裝了jinja2模版引擎愁拭,模版中你仍然可以使用 request, session and g [1] 這些對(duì)象以及像 get_flashed_messages() 函數(shù).
如果你想了解更多模版繼承的東西,可以查看 Template Inheritance 亏吝,它使得可以把像header, navigation and footer的東西放在一個(gè)頁(yè)面中岭埠。

flask可以自動(dòng)忽略過(guò)濾變量中的html標(biāo)記,所以如果你信任它蔚鸥,可以通過(guò) Markup或者|safe 過(guò)濾器標(biāo)簽來(lái)標(biāo)記它是安全的不用過(guò)濾

>>> from flask import Markup
>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
Markup(u'<strong>Hello &lt;blink&gt;hacker&lt;/blink&gt;!</strong>')
>>> Markup.escape('<blink>hacker</blink>')
Markup(u'&lt;blink&gt;hacker&lt;/blink&gt;')
>>> Markup('<em>Marked up</em> &raquo; HTML').striptags()
u'Marked up \xbb HTML'

現(xiàn)在自動(dòng)過(guò)濾并不對(duì)全部模版適用了惜论,自動(dòng)過(guò)濾只對(duì)后綴為.html, .htm, .xml, .xhtml. 的文件適用。

請(qǐng)求數(shù)據(jù)?

flask提供了全局對(duì)象request來(lái)解決客戶端到服務(wù)器的數(shù)據(jù)處理反應(yīng)止喷。你可能會(huì)對(duì)flask如何將它變?yōu)槿挚捎们揖S持它的線程安全馆类。答案就是上下文變量。

flask 能夠確保你在多線程環(huán)境中启盛,獲得活動(dòng)線程正確的數(shù)據(jù)

Context Locals 上下文變量

如果你想理解它是如何工作的,并且測(cè)試一下技羔,那么可以讀一下接下來(lái)的部分僵闯。

flask中的全局對(duì)象和我們通常意義上的不同,它們只是某些特定上下文環(huán)境中的菊部變量的代理藤滥。

想象一個(gè)上下文環(huán)境鳖粟,它是一個(gè)正在處理請(qǐng)求的線程。這時(shí)又來(lái)了一個(gè)請(qǐng)求拙绊,web服務(wù)器決定開(kāi)辟一個(gè)新的線程(或者采用協(xié)程的方式)向图,當(dāng)flask開(kāi)始進(jìn)行內(nèi)部處理這個(gè)請(qǐng)求的時(shí)候,flask計(jì)算出當(dāng)前線程是活動(dòng)的上下文環(huán)境标沪,并且把當(dāng)前的應(yīng)用程序與wsgi環(huán)境同這個(gè)線程綁定起來(lái)榄攀。它通過(guò)一種智能的方式完成程序在不中斷情況下的協(xié)同工作。

wow 這對(duì)你意味著什么金句,意味著你可以不用操心當(dāng)前處于什么上下文環(huán)境而放心的使用全局變量檩赢。當(dāng)然如果你要做一些單元測(cè)試,那就行不通了违寞。這時(shí)猴你發(fā)現(xiàn)代碼中以來(lái)的request對(duì)象沒(méi)有了贞瞒,解決方法就是你自己創(chuàng)建一個(gè)并和上下文綁定偶房。最簡(jiǎn)單的方法是使用test_request_context() context manager這個(gè)上下文管理器,通過(guò)使用with語(yǔ)句綁定一個(gè)test request军浆,然后你就可以使用它了棕洋。

from flask import request

with app.test_request_context('/hello', method='POST'):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert request.path == '/hello'
    assert request.method == 'POST'

或者你也可以傳遞整個(gè)WSGI環(huán)境給 request_context()方法

from flask import request

with app.request_context(environ):
    assert request.method == 'POST'

Request 對(duì)象

表單數(shù)據(jù)

關(guān)于 request的詳細(xì)解釋,可以在這找到乒融。我們接下來(lái)只進(jìn)行常用方法的概述掰盘。
首先你要從flask模塊中導(dǎo)入它

from flask import request

最常用的請(qǐng)求方法是通過(guò)method屬性

@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template('login.html', error=error)

通過(guò)request.form來(lái)獲取表單數(shù)據(jù),如果沒(méi)有這個(gè)屬性簇抵,則拋出 KeyError庆杜,你可以自己捕獲它,或者讓他自動(dòng)使用HTTP 400 錯(cuò)誤頁(yè)面碟摆。

獲取URL中的查詢字符串晃财,可以采用

searchword = request.args.get('key', '')

文件上傳

只要你在你的表單頭中設(shè)置了

enctype="multipart/form-data"

flask可以輕松處理你上傳的文件。上傳的文件被存儲(chǔ)在內(nèi)存或臨時(shí)文件系統(tǒng)中典蜕,你能夠通過(guò)request的files屬性獲取它断盛。所有上傳的文件都被存在這個(gè)屬性字典中,它就像標(biāo)準(zhǔn)的python文件愉舔,并且能夠讓你通過(guò)save方法來(lái)保存它钢猛。下面是個(gè)簡(jiǎn)單示例。

from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

通過(guò)filename屬性轩缤,你能夠獲得客戶端上傳文件的文件名命迈,但它能夠被輕易偽造,所以更安全但方法是通過(guò) secure_filename()方法火的。

from flask import request
from werkzeug.utils import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/' + secure_filename(f.filename))
    ...

更多例子壶愤,點(diǎn)擊 Uploading Files.

Cookies

你可以通過(guò)cookies屬性來(lái)獲取cookies,通過(guò)response對(duì)象的set_cookie 方法來(lái)設(shè)置cookie

from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.
from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

注意到cookies是設(shè)置在response對(duì)象上的馏鹤,當(dāng)你從視圖函數(shù)中返回字符串征椒,F(xiàn)lask會(huì)轉(zhuǎn)化成reponse對(duì)象,你也可以通過(guò) make_response()函數(shù)明確的來(lái)返回它湃累,并且修飾它勃救。
('有時(shí)候需要在返回的時(shí)候設(shè)置headers,這時(shí)候你就需要make_respone函數(shù)來(lái)明確返回一個(gè)response object')
有時(shí)候你想要在response對(duì)象還不存在的時(shí)候創(chuàng)建cookie治力,你就需要利用 Deferred Request Callbacks 模式蒙秒。
Deferred Request Callbacks最重要的關(guān)鍵點(diǎn)是before_request與after_request函數(shù),這兩個(gè)函數(shù)分別是注冊(cè)一個(gè)函數(shù)在request之前和之后執(zhí)行宵统。before_request被注冊(cè)的函數(shù)沒(méi)有參數(shù)税肪,after_request注冊(cè)的函數(shù)有一個(gè)參數(shù) response_class的實(shí)例乘综,并且返回一個(gè)response 對(duì)象描孟。

from flask import g
#自定義裝飾器首有,通過(guò)g來(lái)傳遞數(shù)據(jù)
def after_this_request(f):
    if not hasattr(g, 'after_request_callbacks'):
        g.after_request_callbacks = []
    g.after_request_callbacks.append(f)
    return f

from flask import request
#在處理request前執(zhí)行抖棘,如果沒(méi)有錯(cuò)誤,進(jìn)入視圖函數(shù)執(zhí)行
@app.before_request
def detect_user_language():
    language = request.cookies.get('user_lang')
    if language is None:
        language = guess_language_from_request()
        @after_this_request #自定義裝飾器净捅,將下面的函數(shù)放入g對(duì)象屬性中疑枯,此時(shí)response不存在
        def remember_language(response):
            response.set_cookie('user_lang', language)
    g.language = language

#request在視圖函數(shù)處理返回response后執(zhí)行
@app.after_request
def call_after_request_callbacks(response):
    for callback in getattr(g, 'after_request_callbacks', ()):
        callback(response)
    return response

Redirects and Errors 重定向與錯(cuò)誤

記住redirect 與 abort函數(shù)

from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

默認(rèn)的flask提供一套簡(jiǎn)單的error page,如果想自定義蛔六,使用 errorhandler() 裝飾器:

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

調(diào)用 render_template() 后的404告訴 Flask頁(yè)面沒(méi)找到荆永,默認(rèn)是200,表示一切都好国章。

關(guān)于Responses

flask將返回值轉(zhuǎn)化為response對(duì)象的邏輯規(guī)則如下:
1具钥、如果返回正確類型的response對(duì)象,視圖函數(shù)直接返回液兽。
2骂删、如果返回的是字符串,flask將string與一些默認(rèn)參數(shù)轉(zhuǎn)化為response對(duì)象四啰。
3宁玫、如果是一個(gè)元組,那么必須以(response, status, headers) 或 (response, headers)的形式出現(xiàn)柑晒,至少有一項(xiàng)必須存在欧瘪。status value 將會(huì)覆蓋status,headers可以以列表或字典的形式出現(xiàn)匙赞。

如果你想在視圖中控制返回對(duì)象佛掖,使用make_response函數(shù)

@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template('error.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

Sessions

除request對(duì)象外還有一個(gè)session對(duì)象。session對(duì)象能夠讓你在request之間保存一些對(duì)用戶來(lái)說(shuō)具體的信息涌庭。它是基于cookie的芥被,并為其加密。也就是說(shuō)它只能夠讀脾猛,但不能夠修改撕彤,除非你知道了密碼鱼鸠。

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

@app.route('/')
def index():
    if 'username' in session:
     #Convert the characters &, <, >, ‘, and ” in string s to HTML-safe sequences
        return 'Logged in as %s' % escape(session['username'])  
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))

# set the secret key.  keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

How to generate good secret keys?
如何產(chǎn)生好用的秘鑰

import os
os.urandom(24)

flask 默認(rèn)的是客戶端session猛拴,如果你想處理服務(wù)端的,可以使用flask擴(kuò)展解決蚀狰。

Message Flashing

flask提供應(yīng)用程序與用戶之間良好交互的方法愉昆。它在一個(gè)請(qǐng)求結(jié)束后記錄message,在下一個(gè)(僅下一個(gè))請(qǐng)求中獲得它麻蹋。
flash 例子 更多細(xì)節(jié) Message Flashing

from flask import Flask, flash, redirect, render_template, \
     request, url_for

app = Flask(__name__)
app.secret_key = 'some_secret'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != 'admin' or \
                request.form['password'] != 'secret':
            error = 'Invalid credentials'
        else:
            flash('You were successfully logged in') #這里調(diào)用flash函數(shù)
            return redirect(url_for('index'))
    return render_template('login.html', error=error)

<!doctype html>
<title>My Application</title>
{% with messages = get_flashed_messages() %} #前端調(diào)用該函數(shù)
  {% if messages %}
    <ul class=flashes>
    {% for message in messages %}
      <li>{{ message }}</li>
    {% endfor %}
    </ul>
  {% endif %}
{% endwith %}
{% block body %}{% endblock %}

Logging

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

logger 是一個(gè)標(biāo)準(zhǔn)的logging Logger跛溉,可查看官方的 logging documentation獲得更多信息。

WSGI 中間件

不了解wsgi的可看一下我的另一篇文章帶你快速了解WSGI

(middleware需要把自己偽裝成一個(gè)服務(wù)器,接受應(yīng)用程序芳室,調(diào)用它专肪,同時(shí)middleware還需要把自己偽裝成一個(gè)應(yīng)用程序,傳給服務(wù)器程序堪侯。)
如果你想在你的程序中增加一個(gè)wsgi中間件嚎尤,你可以包裝內(nèi)部的wsgi應(yīng)用程序。你可以像下面這樣做來(lái)使用LighttpdCGIRootFix中間件伍宦。

from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)

Flask 擴(kuò)展

擴(kuò)展都在這里

網(wǎng)站發(fā)布

看這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末芽死,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子次洼,更是在濱河造成了極大的恐慌关贵,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卖毁,死亡現(xiàn)場(chǎng)離奇詭異揖曾,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)势篡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門翩肌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人禁悠,你說(shuō)我怎么就攤上這事念祭。” “怎么了碍侦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵粱坤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我瓷产,道長(zhǎng)站玄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任濒旦,我火速辦了婚禮株旷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尔邓。我一直安慰自己晾剖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布梯嗽。 她就那樣靜靜地躺著齿尽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灯节。 梳的紋絲不亂的頭發(fā)上循头,一...
    開(kāi)封第一講書(shū)人閱讀 51,604評(píng)論 1 305
  • 那天绵估,我揣著相機(jī)與錄音,去河邊找鬼卡骂。 笑死国裳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的全跨。 我是一名探鬼主播躏救,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼螟蒸!你這毒婦竟也來(lái)了盒使?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤七嫌,失蹤者是張志新(化名)和其女友劉穎少办,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體诵原,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡英妓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绍赛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔓纠。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吗蚌,靈堂內(nèi)的尸體忽然破棺而出腿倚,到底是詐尸還是另有隱情,我是刑警寧澤蚯妇,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布敷燎,位于F島的核電站,受9級(jí)特大地震影響箩言,放射性物質(zhì)發(fā)生泄漏硬贯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一陨收、第九天 我趴在偏房一處隱蔽的房頂上張望饭豹。 院中可真熱鬧,春花似錦务漩、人聲如沸拄衰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肾砂。三九已至列赎,卻和暖如春宏悦,著一層夾襖步出監(jiān)牢的瞬間镐确,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工饼煞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留源葫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓砖瞧,卻偏偏與公主長(zhǎng)得像息堂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子块促,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 22年12月更新:個(gè)人網(wǎng)站關(guān)停荣堰,如果仍舊對(duì)舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,184評(píng)論 22 257
  • [TOC]一直想做源碼閱讀這件事,總感覺(jué)難度太高時(shí)間太少竭翠,可望不可見(jiàn)振坚。最近正好時(shí)間充裕,決定試試做一下斋扰,并記錄一下...
    何柯君閱讀 7,187評(píng)論 3 98
  • flask源碼分析 1. 前言 本文將基于flask 0.1版本(git checkout 8605cc3)來(lái)分析...
    甘尼克斯_閱讀 2,711評(píng)論 1 0
  • 快速啟動(dòng) 是不是很渴望馬上開(kāi)始岸砂恕?這篇文檔將會(huì)很好的向你介紹Flask传货。假設(shè)你已經(jīng)安裝好了Flask屎鳍。如果還沒(méi)有安...
    催眠_(dá)a363閱讀 683評(píng)論 0 1
  • 一切都似順其自然,從青澀到成熟问裕,從仲夏入初秋逮壁,一起見(jiàn)證我們的六年。七月粮宛,夏季過(guò)半貌踏,有烈日蟬鳴,清風(fēng)徐來(lái)窟勃,...
    Ronggee閱讀 297評(píng)論 0 0