[轉]Flask --- 框架快速入門

?

From:http://docs.jinkan.org/docs/flask/quickstart.html

Flask 用戶指南:http://docs.jinkan.org/docs/flask/index.html

w3cschool.cn?的?Flask?教程:https://www.w3cschool.cn/flask/

《Flask Web開發:基于Python的Web應用開發實戰》第2版中文PDF,324頁,帶書簽目錄,文字能夠復制粘貼;配套源代碼;
下載: https://pan.baidu.com/s/1qhCaPeX41vltmeI-XFVLIA? ? 提取碼: v9w5

Flask大型教程項目:http://www.pythondoc.com/flask-mega-tutorial/index.html#

?

?

?

一個最小的應用

?

迫不及待要開始了嗎?本頁提供了一個很好的 Flask 介紹,并假定你已經安裝好了 Flask。

如果沒有,請跳轉到?安裝?章節 (?http://docs.jinkan.org/docs/flask/installation.html#installation )。

一個最小的 Flask 應用看起來會是這樣:
?

from flask import Flask
app = Flask(__name__)@app.route('/')def hello_world():return 'Hello World!'if __name__ == '__main__':app.run()
把它保存為?hello.py?(或是類似的),然后用 Python 解釋器來運行。 確保你的應用文件名不是?flask.py?,因為這將與 Flask 本身沖突。

$ python hello.py
?* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

現在訪問?http://127.0.0.1:5000/?,你會看見 Hello World 問候。

那么,這段代碼做了什么?

  1. 首先,我們導入了?Flask?類。這個類的實例將會是我們的 WSGI 應用程序。
  2. 接下來,我們創建一個該類的實例,第一個參數是應用模塊或者包的名稱。 如果你使用單一的模塊(如本例),你應該使用?__name__?,因為模塊的名稱將會因其作為單獨應用啟動還是作為模塊導入而有不同( 也即是?'__main__'?或實際的導入名)。這是必須的,這樣 Flask 才知道到哪去找模板、靜態文件等等。詳情見?Flask的文檔。
  3. 然后,我們使用?route()?裝飾器告訴 Flask 什么樣的URL 能觸發我們的函數。
  4. 這個函數的名字也在生成 URL 時被特定的函數采用,這個函數返回我們想要顯示在用戶瀏覽器中的信息。
  5. 最后我們用?run()?函數來讓應用運行在本地服務器上。 其中?if?__name__?=='__main__':?確保服務器只會在該腳本被 Python 解釋器直接執行的時候才會運行,而不是作為模塊導入的時候。

欲關閉服務器,按 Ctrl+C。

?

外部可訪問的服務器

如果你運行了這個服務器,你會發現它只能從你自己的計算機上訪問,網絡中其它任何的地方都不能訪問。在調試模式下,用戶可以在你的計算機上執行任意 Python 代碼。因此,這個行為是默認的。

如果你禁用了?debug?或信任你所在網絡的用戶,你可以簡單修改調用?run()?的方法使你的服務器公開可用,如下:

app.run(host='0.0.0.0')

這會讓操作系統監聽所有公網 IP。

?

?

調試模式

?

雖然?run()?方法適用于啟動本地的開發服務器,但是你每次修改代碼后都要手動重啟它。這樣并不夠優雅,而且 Flask 可以做到更好。如果你啟用了調試支持,服務器會在代碼修改后自動重新載入,并在發生錯誤時提供一個相當有用的調試器。

有兩種途徑來啟用調試模式。一種是直接在應用對象上設置:

app.debug = Trueapp.run()

另一種是作為 run 方法的一個參數傳入:

app.run(debug=True)

兩種方法的效果完全相同。

注意:盡管交互式調試器在允許 fork 的環境中無法正常使用(也即在生產服務器上正常使用幾乎是不可能的),但它依然允許執行任意代碼。這使它成為一個巨大的安全隱患,因此它?絕對不能用于生產環境?。

運行中的調試器截圖:

?

screenshot of debugger in action

想用其它的調試器? 參見?調試器操作?。

?

?

路由

?

現代 Web 應用的 URL 十分優雅,易于人們辨識記憶,這一點對于那些面向使用低速網絡連接移動設備訪問的應用特別有用。如果可以不訪問索引頁,而是直接訪問想要的那個頁面,他們多半會笑逐顏開而再度光顧。

如上所見,?route()?裝飾器把一個函數綁定到對應的 URL 上。

這里是一些基本的例子:

from flask import Flaskapp = Flask(__name__)@app.route('/')def index():return 'Index Page'@app.route('/hello')def hello():return 'Hello World'if __name__ == '__main__':app.run()

但是,不僅如此!你可以構造含有動態部分的 URL,也可以在一個函數上附著多個規則。

?

變量規則

要給 URL 添加變量部分,你可以把這些特殊的字段標記為?<variable_name>?, 這個部分將會作為命名參數傳遞到你的函數。規則可以用?<converter:variable_name>?指定一個可選的轉換器。這里有一些不錯的例子:

?

from flask import Flask
app = Flask(__name__)
@app.route('/user/<username>')def show_user_profile(username):# show the user profile for that userreturn 'User %s' % username
@app.route('/post/<int:post_id>')def show_post(post_id):# show the post with the given id, the id is an integerreturn 'Post %d' % post_id
if __name__ == '__main__':app.run()
轉換器有下面幾種:
int接受整數
float同?int?,但是接受浮點數
path和默認的相似,但也接受斜線

唯一 URL / 重定向行為

Flask 的 URL 規則基于 Werkzeug 的路由模塊。這個模塊背后的思想是基于 Apache 以及更早的 HTTP 服務器主張的先例,保證優雅且唯一的 URL。

以這兩個規則為例:

from flask import Flask
app = Flask(__name__)
@app.route('/projects/')def projects():return 'The project page'
@app.route('/about')def about():return 'The about page'
if __name__ == '__main__':app.run()

雖然它們看起來著實相似,但它們結尾斜線的使用在 URL?定義?中不同。

  1. 第一種情況中,指向?projects?的規范 URL 尾端有一個斜線。這種感覺很像在文件系統中的文件夾。訪問一個結尾不帶斜線的 URL 會被 Flask 重定向到帶斜線的規范 URL 去。
  2. 第二種情況的 URL 結尾不帶斜線,類似 UNIX-like 系統下的文件的路徑名。訪問結尾帶斜線的 URL 會產生一個 404 “Not Found” 錯誤。這個行為使得在遺忘尾斜線時,允許關聯的 URL 接任工作,與 Apache 和其它的服務器的行為并無二異。此外,也保證了 URL 的唯一,有助于避免搜索引擎索引同一個頁面兩次。

?

構造 URL

如果 Flask 能匹配 URL,那么 Flask 可以生成它們嗎?當然可以。你可以用?url_for()來給指定的函數構造 URL。它接受函數名作為第一個參數,也接受對應 URL 規則的變量部分的命名參數。未知變量部分會添加到 URL 末尾作為查詢參數。這里有一些例子:

>>> from flask import Flask, url_for>>> app = Flask(__name__)>>> @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')... print url_for('login', next='/')... print url_for('profile', username='John Doe')...//login/login?next=//user/John%20Doe


????

(這里也用到了?test_request_context()?方法,下面會解釋。即使我們正在通過 Python 的 shell 進行交互,它依然會告訴 Flask 要表現為正在處理一個請求。請看下面的解釋。?環境局部變量?)

為什么你要構建 URL 而非在模板中硬編碼?這里有三個絕妙的理由:

  1. 反向構建通常比硬編碼的描述性更好。更重要的是,它允許你一次性修改 URL, 而不是到處邊找邊改。
  2. URL 構建會轉義特殊字符和 Unicode 數據,免去你很多麻煩。
  3. 如果你的應用不位于 URL 的根路徑(比如,在?/myapplication?下,而不是?/?),?url_for()?會妥善處理這個問題。

?

HTTP 方法

HTTP (與 Web 應用會話的協議)有許多不同的訪問 URL 方法。默認情況下,路由只回應?GET?請求,但是通過?route()?裝飾器傳遞?methods?參數可以改變這個行為。這里有一些例子:


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

如果存在?GET?,那么也會替你自動地添加?HEAD,無需干預。它會確保遵照?HTTP RFC(描述 HTTP 協議的文檔)處理?HEAD?請求,所以你可以完全忽略這部分的 HTTP 規范。同樣,自從 Flask 0.6 起, 也實現了?OPTIONS?的自動處理。

你不知道一個 HTTP 方法是什么?不必擔心,這里會簡要介紹 HTTP 方法和它們為什么重要:

HTTP 方法(也經常被叫做“謂詞”)告知服務器,客戶端想對請求的頁面??些什么。下面的都是非常常見的方法:

  1. GET:瀏覽器告知服務器:只?獲取?頁面上的信息并發給我。這是最常用的方法。
  2. HEAD:瀏覽器告訴服務器:欲獲取信息,但是只關心?消息頭?。應用應像處理?GET?請求一樣來處理它,但是不分發實際內容。在 Flask 中你完全無需 人工 干預,底層的 Werkzeug 庫已經替你打點好了。
  3. POST:瀏覽器告訴服務器:想在 URL 上?發布?新信息。并且,服務器必須確保 數據已存儲且僅存儲一次。這是 HTML 表單通常發送數據到服務器的方法。
  4. PUT:類似?POST?但是服務器可能觸發了存儲過程多次,多次覆蓋掉舊值。你可 能會問這有什么用,當然這是有原因的。考慮到傳輸中連接可能會丟失,在 這種 情況下瀏覽器和服務器之間的系統可能安全地第二次接收請求,而 不破壞其它東西。因為?POST它只觸發一次,所以用?POST?是不可能的。
  5. DELETE:刪除給定位置的信息。
  6. OPTIONS:給客戶端提供一個敏捷的途徑來弄清這個 URL 支持哪些 HTTP 方法。 從 Flask 0.6 開始,實現了自動處理。

有趣的是,在 HTML4 和 XHTML1 中,表單只能以?GET?和?POST?方法提交到服務器。但是 JavaScript 和未來的 HTML 標準允許你使用其它所有的方法。此外,HTTP 最近變得相當流行,瀏覽器不再是唯一的 HTTP 客戶端。比如,許多版本控制系統就在使用 HTTP。

?

?

靜態文件

?

動態 web 應用也會需要靜態文件,通常是 CSS 和 JavaScript 文件。理想狀況下, 你已經配置好 Web 服務器來提供靜態文件,但是在開發中,Flask 也可以做到。 只要在你的包中或是模塊的所在目錄中創建一個名為?static?的文件夾,在應用中使用?/static?即可訪問。

給靜態文件生成 URL ,使用特殊的?'static'?端點名:

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

這個文件應該存儲在文件系統上的?static/style.css?。

?

?

模板渲染

?

用 Python 生成 HTML 十分無趣,而且相當繁瑣,因為你必須手動對 HTML 做轉義來保證應用的安全。為此,Flask 配備了?Jinja2?模板引擎。

你可以使用?render_template()?方法來渲染模板。你需要做的一切就是將模板名和你想作為關鍵字的參數傳入模板的變量。這里有一個展示如何渲染模板的簡例:

from flask import render_template@app.route('/hello/')@app.route('/hello/<name>')def hello(name=None):return render_template('hello.html', name=name)

?

Flask 會在?templates?文件夾里尋找模板。所以,如果你的應用是個模塊,這個文件夾應該與模塊同級;如果它是一個包,那么這個文件夾作為包的子目錄:

情況 1: 模塊:


/application.py/templates/hello.html

情況 2: 包:


/application/__init__.py/templates/hello.html


關于模板,你可以發揮 Jinja2 模板的全部實例。更多信息請見?Jinja2 模板文檔?。

這里有一個模板實例:


<!doctype html><title>Hello from Flask</title>{% if name %}<h1>Hello {{ name }}!</h1>{% else %}<h1>Hello World!</h1>{% endif %}


在模板里,你也可以訪問?request?、?session?和?g?[1]?對象, 以及?get_flashed_messages()?函數。模板繼承讓模板用起來相當順手。如欲了解繼承的工作機理,請跳轉到?模板繼承?模式的文檔。最起碼,模板繼承能使特定元素 (比如頁眉、導航欄和頁腳)可以出現在所有的頁面。

自動轉義功能默認是開啟的,所以如果?name?包含 HTML ,它將會被自動轉義。如果你能信任一個變量,并且你知道它是安全的(例如一個模塊把 Wiki 標記轉換為 HTML),你可以用?Markup?類或?|safe?過濾器在模板中把它標記為安全的。在 Jinja 2 文檔中,你會看到更多的例子。

這里是一個?Markup?類如何使用的簡單介紹:

>>> 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'


??????

在 0.5 版更改:?自動轉義不再在所有模板中啟用。下列擴展名的模板會觸發自動轉義:.html?、?.htm?、.xml?、?.xhtml?。從字符串加載的模板會禁用自動轉義。

[1]不確定?g?對象是什么?它允許你按需存儲信息, 查看(?g?)對象的文檔和?在 Flask 中使用 SQLite 3?的文檔以獲取更多信息。

?

?

訪問請求數據

?

對于 Web 應用,與客戶端發送給服務器的數據交互至關重要。在 Flask 中由全局的?request?對象來提供這些信息。如果你有一定的 Python 經驗,你會好奇,為什么這個對象是全局的,為什么 Flask 還能保證線程安全。答案是環境作用域:

?

環境局部變量

內幕:如果你想理解其工作機制及如何利用環境局部變量實現自動化測試,請閱讀此節,否則可跳過。

Flask 中的某些對象是全局對象,但卻不是通常的那種。這些對象實際上是特定環境的局部對象的代理。雖然很拗口,但實際上很容易理解。

想象一下處理線程的環境。一個請求傳入,Web 服務器決定生成一個新線程( 或者別的什么東西,只要這個底層的對象可以勝任并發系統,而不僅僅是線程)。 當 Flask 開始它內部的請求處理時,它認定當前線程是活動的環境,并綁定當前的應用和 WSGI 環境到那個環境上(線程)。它的實現很巧妙,能保證一個應用調用另一個應用時不會出現問題。

所以,這對你來說意味著什么?除非你要做類似單元測試的東西,否則你基本上可以完全無視它。你會發現依賴于一段請求對象的代碼,因沒有請求對象無法正常運行。解決方案是,自行創建一個請求對象并且把它綁定到環境中。單元測試的最簡單的解決方案是:用?test_request_context()?環境管理器。結合?with?聲明,綁定一個測試請求,這樣你才能與之交互。下面是一個例子:
???????

from flask import requestwith 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'

另一種可能是:傳遞整個 WSGI 環境給?request_context()?方法:
???????

from flask import requestwith app.request_context(environ):assert request.method == 'POST'

?

請求對象

API 章節對請求對象作了詳盡闡述(參見?request?),因此這里不會贅述。此處寬泛介紹一些最常用的操作。首先從?flask?模塊里導入它:

from flask import request

當前請求的 HTTP 方法可通過?method?屬性來訪問。通過:attr:~flask.request.form?屬性來訪問表單數據(?POST?或?PUT?請求提交的數據)。這里有一個用到上面提到的那兩個屬性的完整實例:
???????


@app.route('/login', methods=['POST', 'GET'])def login():error = Noneif 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 invalidreturn render_template('login.html', error=error)

當訪問?form?屬性中的不存在的鍵會發生什么?會拋出一個特殊的?KeyError?異常。你可以像捕獲標準的?KeyError?一樣來捕獲它。 如果你不這么做,它會顯示一個 HTTP 400 Bad Request 錯誤頁面。所以,多數情況下你并不需要干預這個行為。

你可以通過?args?屬性來訪問 URL 中提交的參數 (??key=value?):

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

我們推薦用?get?來訪問 URL 參數或捕獲?KeyError?,因為用戶可能會修改 URL,向他們展現一個 400 bad request 頁面會影響用戶體驗。

欲獲取請求對象的完整方法和屬性清單,請參閱?request?的文檔。

?

文件上傳

用 Flask 處理文件上傳很簡單。只要確保你沒忘記在 HTML 表單中設置enctype="multipart/form-data"?屬性,不然你的瀏覽器根本不會發送文件。

已上傳的文件存儲在內存或是文件系統中一個臨時的位置。你可以通過請求對象的?files屬性訪問它們。每個上傳的文件都會存儲在這個字典里。它表現近乎為一個標準的 Python?file?對象,但它還有一個?save()?方法,這個方法允許你把文件保存到服務器的文件系統上。這里是一個用它保存文件的例子:


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')...
???????

如果你想知道上傳前文件在客戶端的文件名是什么,你可以訪問?filename?屬性。但請記住, 永遠不要信任這個值,這個值是可以偽造的。如果你要把文件按客戶端提供的文件名存儲在服務器上,那么請把它傳遞給 Werkzeug 提供的?secure_filename()?函數:
???????

from flask import requestfrom werkzeug 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))...

一些更好的例子,見?上傳文件?模式。

?

Cookies

你可以通過?cookies?屬性來訪問 Cookies,用響應對象的?set_cookie?方法來設置 Cookies。請求對象的?cookies?屬性是一個內容為客戶端提交的所有 Cookies 的字典。如果你想使用會話,請不要直接使用 Cookies,請參考?會話?一節。在 Flask 中,已經注意處理了一些 Cookies 安全細節。

讀取 cookies:

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.

存儲 cookies:

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

可注意到的是,Cookies 是設置在響應對象上的。由于通常視圖函數只是返回字符串,之后 Flask 將字符串轉換為響應對象。如果你要顯式地轉換,你可以使用?make_response()函數然后再進行修改。

有時候你想設置 Cookie,但響應對象不能醋在。這可以利用?延遲請求回調?模式實現。

為此,也可以閱讀?關于響應?。

?

?

重定向和錯誤

?

你可以用?redirect()?函數把用戶重定向到其它地方。放棄請求并返回錯誤代碼,用?abort()?函數。這里是一個它們如何使用的例子:

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()

這是一個相當無意義的例子因為用戶會從主頁重定向到一個不能訪問的頁面 (401 意味著禁止訪問),但是它展示了重定向是如何工作的。

默認情況下,錯誤代碼會顯示一個黑白的錯誤頁面。如果你要定制錯誤頁面, 可以使用?errorhandler()?裝飾器:


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

注意?render_template()?調用之后的?404?。這告訴 Flask,該頁的錯誤代碼是 404 ,即沒有找到。默認為 200,也就是一切正常。

?

?

關于響應

?

視圖函數的返回值會被自動轉換為一個響應對象。如果返回值是一個字符串, 它被轉換為該字符串為主體的、狀態碼為?200?OK``的?、?MIME?類型是?``text/html?的響應對象。Flask 把返回值轉換為響應對象的邏輯是這樣:

  1. 如果返回的是一個合法的響應對象,它會從視圖直接返回。
  2. 如果返回的是一個字符串,響應對象會用字符串數據和默認參數創建。
  3. 如果返回的是一個元組,且元組中的元素可以提供額外的信息。這樣的元組必須是?(response,?status,?headers)?的形式,且至少包含一個元素。?status?值會覆蓋狀態代碼,?headers?可以是一個列表或字典,作為額外的消息標頭值。
  4. 如果上述條件均不滿足, Flask 會假設返回值是一個合法的 WSGI 應用程序,并轉換為一個請求對象。

如果你想在視圖里操縱上述步驟結果的響應對象,可以使用?make_response()?函數。

譬如你有這樣一個視圖:

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

你只需要把返回值表達式傳遞給?make_response()?,獲取結果對象并修改,然后再返回它:

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

?

?

會話

?

除請求對象之外,還有一個?session?對象。它允許你在不同請求間存儲特定用戶的信息。它是在 Cookies 的基礎上實現的,并且對 Cookies 進行密鑰簽名。這意味著用戶可以查看你 Cookie 的內容,但卻不能修改它,除非用戶知道簽名的密鑰。

要使用會話,你需要設置一個密鑰。這里介紹會話如何工作:

from flask import Flask, session, redirect, url_for, escape, requestapp = Flask(__name__)@app.route('/')def index():if 'username' in session: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 action="" 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 theresession.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'

這里提到的?escape()?可以在你模板引擎外做轉義(如同本例)。

如何生成強壯的密鑰:隨機的問題在于很難判斷什么是真隨機。一個密鑰應該足夠隨機。你的操作系統可以基于一個密鑰隨機生成器來生成漂亮的隨機值,這個值可以用來做密鑰:

>>> import os>>> os.urandom(24)'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'

把這個值復制粘貼進你的代碼中,你就有了密鑰。

使用基于 cookie 的會話需注意: Flask 會將你放進會話對象的值序列化至 Cookies。如果你發現某些值在請求之間并沒有持久存在,然而確實已經啟用了 Cookies,但也沒有得到明確的錯誤信息。這時,請檢查你的頁面響應中的 Cookies 的大小,并與 Web 瀏覽器所支持的大小對比。

?

?

消息閃現

?

反饋,是良好的應用和用戶界面的重要構成。如果用戶得不到足夠的反饋,他們很可能開始厭惡這個應用。 Flask 提供了消息閃現系統,可以簡單地給用戶反饋。 消息閃現系統通常會在請求結束時記錄信息,并在下一個(且僅在下一個)請求中訪問記錄的信息。展現這些消息通常結合要模板布局。

使用?flash()?方法可以閃現一條消息。要操作消息本身,請使用get_flashed_messages()?函數,并且在模板中也可以使用。完整的例子見?消息閃現?部分。

?

?

日志記錄

?

0.3 新版功能.

有時候你會處于這樣一種境地,你處理的數據本應該是正確的,但實際上不是。 比如,你會有一些向服務器發送請求的客戶端代碼,但請求顯然是畸形的。這可能是用戶篡改了數據,或是客戶端代碼的粗制濫造。大多數情況下,正常地返回?400?Bad?Request?就可以了,但是有時候不能這么做,并且要讓代碼繼續運行。

你可能依然想要記錄下,是什么不對勁。這時日志記錄就派上了用場。從 Flask 0.3 開始,Flask 就已經預置了日志系統。

這里有一些調用日志記錄的例子:

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

附帶的?logger?是一個標準日志類?Logger?,所以更多信息請查閱?logging 的文檔?。

?

?

整合 WSGI 中間件

?

如果你想給你的應用添加 WSGI 中間件,你可以封裝內部 WSGI 應用。例如若是你想用 Werkzeug 包中的某個中間件來應付 lighttpd 中的 bugs ,可以這樣做:


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

?

?

部署到 Web 服務器

?

準備好部署你的 Flask 應用了?你可以立即部署到托管平臺來圓滿完成快速入門,以下廠商均向小項目提供免費的方案:

  • 在 Heroku 上部署 Flask
  • 在 dotCloud 上部署 Flask?附?Flask 的具體說明

托管 Flask 應用的其它選擇:

  • 在 Webfaction 上部署 Flask
  • 在 Google App Engine 上部署 Flask
  • 用 Localtunnel 共享你的本地服務器

如果你有自己的主機,并且準備自己托管,參見?部署選擇?章節。

?

?

?


---------------------
作者:擒賊先擒王
來源:CSDN
原文:https://blog.csdn.net/freeking101/article/details/100174215
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285037.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285037.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285037.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【ArcGIS Pro微課1000例】0010:ArcGIS Pro導入ArcMap樣式符號庫——以國土三調樣式為例

樣式是用于存儲符號、顏色、配色方案、標注放置和布局項目的容器。 它們可以提升地圖、場景和布局的一致性和標準化程度。 您創作地圖、場景和布局時所使用的符號庫和顏色選取器由存儲在樣式中的項目填充。 ArcMap、ArcGlobe 或 ArcScene 的桌面樣式不能直接在 ArcGIS Pro 中使…

Windows WMIC命令使用詳解(附實例)

第一次執行WMIC命令時&#xff0c;Windows首先要安裝WMIC&#xff0c;然后顯示出WMIC的命令行提示符。在WMIC命令行提示符上&#xff0c;命令以交互的方式執行執行“wmic”命令啟動WMIC命令行環境。這個命令可以在XP或 .NET Server的標準命令行解釋器&#xff08;cmd.exe&#…

MAC usb啟動盤制作

1.從App Store 下載OS 2.磁盤工具格式化磁盤默認即可 3. 為啥截圖&#xff0c;因為有些是不一樣的&#xff0c;建議使用 Tab建&#xff0c; 未命名則是你移動U盤命名的名稱。 4.完成&#xff1a;所有的命令完成的話&#xff0c; 終端界面中會出現 Erasing Disk: 0%...10%...…

【ArcGIS Pro微課1000例】0011:ArcGIS Pro范圍內匯總工具的巧妙使用——以甘肅省各地區內河流總長度計算為例

文章目錄 問題描述范圍內匯總工具介紹# 案例實現問題描述 統計甘肅省各個地區界內河流的總長度,如下圖所示。 范圍內匯總工具介紹 在ArcMap中可以實現河流總長度的統計,具體操作可以參考:【ArcGIS風暴】ArcGIS獲取一個省各個地區界內的河流的總長度–以甘肅省為例,在ArcG…

C語言試題177之實現二分查找算法,折半查找算法

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目: 本實例…

力扣(leetcode)第20題有效的括號(Python)

20.有效的括號 題目鏈接&#xff1a;20.有效的括號 給定一個只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判斷字符串是否有效。 有效字符串需滿足&#xff1a; 左括號必須用相同類型的右括…

30分鐘掌握ES6/ES2015核心內容

2019獨角獸企業重金招聘Python工程師標準>>> ECMAScript 6&#xff08;以下簡稱ES6&#xff09;是JavaScript語言的下一代標準。因為當前版本的ES6是在2015年發布的&#xff0c;所以又稱ECMAScript 2015。 也就是說&#xff0c;ES6就是ES2015。 雖然目前并不是所有瀏…

Windows 11 22H2 22621.290 和 22622.290 推送

面向 Beta 頻道的 Windows 預覽體驗成員&#xff0c;微軟現已推送 Windows 11 預覽版 Build 22621.290 和 22622.290。微軟宣布 Beta 頻道Windows 11 預覽版啟用全新體驗&#xff0c;分為兩組進行測試。通過兩組 Windows 預覽體驗成員的使用數據和反饋&#xff0c;以更好的測試…

js數組中的find、filter、sort

準備測試數據 var data [{name:"Jackie",id: "122"}, {name:"Tony2",id: "121"}, {name:"Tony",id: "121"}]; find 查找 返回第一個符合條件的結果 data.find(user>user.id121)--結果 {name: "Tony2&q…

【ArcGIS Pro微課1000例】0012:ArcGIS Pro屬性表中文亂碼完美解決辦法匯總

如圖所示,安裝完ArcGIS Pro后,由于計算機系統和應用軟件字符編碼的問題,導致加載矢量數據并打開屬性表后,會發現中文字段出現了亂碼。 屬性表中文亂碼: 屬性表中文正常: 事實上,ArcMap中也會出現中文屬性表亂碼的情況。 亂碼的出現會給學習和工作帶來很大不便,因此本…

C語言試題178之實現分塊查找算法,索引順序查找算法

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目: 例如,…

dubbo中的Filter順序是如何確定的

2019獨角獸企業重金招聘Python工程師標準>>> 服務提供方的過濾器被調用順序&#xff1a; EchoFilter->ClassLoaderFilter->GenericFilter->ContextFilter->(這4個是在代碼中指定的) ExceptionFilter-> TimeoutFilter ->MonitorFilter-> TraceF…

java提示找不到或無法加載主類

背景 默許jdk的配置大家都沒有問題&#xff0c;執行java&#xff0c;javac無報錯&#xff0c;但今天在嘗試在本地起來kafka的時候&#xff0c;提示java 找不到或無法加載主類&#xff0c;然后日志中提示 Files 找不到或無法加載主類&#xff1b;C:\Program 分析 其實很輕松的猜…

Dapr v1.8 正式發布

Dapr是一套開源、可移植的事件驅動型運行時&#xff0c;允許開發人員輕松立足云端與邊緣位置運行彈性、微服務、無狀態以及有狀態等應用程序類型。Dapr能夠確保開發人員專注于編寫業務邏輯&#xff0c;而不必分神于解決分布式系統難題&#xff0c;由此顯著提高生產力并縮短開發…

[轉]WebView長按彈出復制粘貼

ActionMode簡介 ActionMode是android3.0之后出現的一種菜單選擇模式 ActionMode的創建 ActionMode的使用特別的簡單&#xff0c;主要用到兩個方法&#xff0c;startActionMode和ActionMode.Callback()&#xff0c;startActionMode:開啟我們的菜單&#xff0c;ActionMode.Cal…

深夜爆肝:萬字長文3種語言實現Huffman樹(強烈建議三連)

文章目錄一、C語言能干大事1. C語言下Huffman樹的計算過程分析2. C語言下Huffman樹的編程二、C#語言也不賴1. C#下Huffman類的設計2. C#中界面設計3. 建立測試數據并顯示Huffman樹4. 輸入任意一組數據&#xff0c;完成構造Huffman樹三、JavaScript語言不愛聽了1. JavaScript下H…

C語言試題179之實現堆排序算法

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目: 實現堆…

SQL Server Update 所有表的某一列(列名相同,類型相同)數值

DECLARE sql VARCHAR(5000); WITH T AS (SELECT SchemaName c.TABLE_SCHEMA,TableName c.TABLE_NAME,ColumnName c.COLUMN_NAME,DataType DATA_TYPE,sql update c.TABLE_NAME set c.COLUMN_NAME 2017-11-20 -----------執行語句FROM INFORMATION_SCHEMA.COLUMNS …

C語言試題180之實現實現字符串strcpy函數

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目: 實現字…

[轉]關于數據中臺、數據平臺、數據倉庫、數據湖等數據概念的對比解析

前言 2010年左右&#xff0c;還是在上學的時候&#xff0c;學過一門課程叫《數據倉庫與數據挖掘》&#xff0c;那還是屬于傳統數據的時代&#xff0c;我們會討論什么是數據倉庫&#xff1f;什么是數據集市&#xff1f;數據倉庫和數據庫有什么區別&#xff1f;等等&#xff0c;…