1. 程式人生 > >python flask框架詳解

python flask框架詳解

Flask是一個Python編寫的Web 微框架,讓我們可以使用Python語言快速實現一個網站或Web服務。本文參考自[Flask官方文件](https://flask.palletsprojects.com/en/0.12.x/), 英文不好的同學也可以參考[中文文件](https://dormousehole.readthedocs.io/en/latest/) # 1.安裝flask ```bash pip install flask ``` # 2.簡單上手 一個最小的 Flask 應用如下: ```python from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run() ``` >程式碼解析: >1、首先我們匯入了 Flask 類。 該類的例項將會成為我們的 WSGI 應用。 >2、接著我們建立一個該類的例項。第一個引數是應用模組或者包的名稱。如果你使用 一個單一模組(就像本例),那麼應當使用 __name__ ,因為名稱會根據這個 模組是按應用方式使用還是作為一個模組匯入而發生變化(可能是 ‘__main__’ , 也可能是實際匯入的名稱)。這個引數是必需的,這樣 Flask 才能知道在哪裡可以 找到模板和靜態檔案等東西 >3、然後我們使用 route() 裝飾器來告訴 Flask 觸發函式的 URL 。 >4、函式名稱被用於生成相關聯的 URL 。函式最後返回需要在使用者瀏覽器中顯示的資訊。 執行結果: ```python * Serving Flask app "flask_demo" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) ``` 訪問:http://127.0.0.1:5000/ ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210301233259992.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) ```python app.route(rule, options) ``` - rule 引數表示與該函式的URL繫結。 - options 是要轉發給基礎Rule物件的引數列表。 在上面的示例中,'/ ' URL與hello_world()函式繫結。因此,當在瀏覽器中開啟web伺服器的主頁時,將呈現該函式的輸出。 最後,Flask類的run()方法在本地開發伺服器上執行應用程式。 ```python app.run(host, port, debug, options) ``` 所有引數都是可選的 - host:要監聽的主機名。 預設為127.0.0.1(localhost)。設定為“0.0.0.0”以使伺服器在外部可用 - port :預設值為5000 - debug:預設為false。 如果設定為true,則提供除錯資訊,可以自動過載程式碼並顯示除錯資訊 - options:要轉發到底層的Werkzeug伺服器。 ## 2.1 除錯模式 雖然 flask 命令可以方便地啟動一個本地開發伺服器,但是每次應用程式碼 修改之後都需要手動重啟伺服器。這樣不是很方便, Flask 可以做得更好。如果你開啟 除錯模式,那麼伺服器會在修改應用程式碼之後自動重啟,並且當應用出錯時還會提供一個 有用的偵錯程式。 在命令列中,如果需要開啟所有開發功能(包括除錯模式),那麼要在執行伺服器之前匯出 FLASK_ENV 環境變數並把其設定為 development: ```python $ export FLASK_ENV=development $ flask run ``` 在程式碼中,在執行或將除錯引數傳遞給run()方法之前,通過將application物件的debug屬性設定為True來啟用Debug模式。 ```python app.debug = True app.run() # 或者 app.run(debug = True) ``` ## 2.2 繫結IP和埠 預設情況下,Flask繫結IP為127.0.0.1,埠為5000。我們也可以通過下面的方式自定義: ```python app.run(host='0.0.0.0', port=80, debug=True) ``` 0.0.0.0代表電腦所有的IP。80是HTTP網站服務的預設埠。什麼是預設?比如,我們訪問網站http://www.example.com,其實是訪問的http://www.example.com:80,只不過:80可以省略不寫。 # 3.Flask 路由 現代Web框架使用路由技術來幫助使用者記住應用程式URL。可以直接訪問所需的頁面,而無需從主頁導航。 Flask中的route()裝飾器用於將URL繫結到函式。例如: ```python @app.route('/hello') def hello_world(): return 'hello world' ``` 在這裡,URL` '/ hello' `規則繫結到hello_world()函式。 因此,如果使用者訪問`http://localhost:5000/hello` URL,hello_world()函式的輸出將在瀏覽器中呈現。 application物件的add_url_rule()函式也可用於將URL與函式繫結,如上例所示,使用route()裝飾器的目的也由以下表示: ```python def hello_world(): return 'hello world' app.add_url_rule('/', 'hello', hello_world) ``` # 4.Flask 變數規則 通過向規則引數新增變數部分,可以動態構建URL。此變數部分標記為` `。它作為關鍵字引數傳遞給與規則相關聯的函式。 在以下示例中,route()裝飾器的規則引數包含附加到URL` '/hello' `的``。 因此,如果在瀏覽器中輸入http://localhost:5000/hello/chenshifeng作為URL,則'chenshifeng'將作為引數提供給 hello()函式。 ```python #!/usr/bin/python # -*- coding: UTF-8 -*- """ @author:chenshifeng @file:flask_demo.py @time:2021/03/01 """ from flask import Flask app = Flask(__name__) @app.route('/hello/') def hello_name(name): return 'Hello %s!' % name if __name__ == '__main__': app.run(debug=True) ``` 執行,訪問:http://localhost:5000/hello/chenshifeng ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302000116204.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 除了預設字串變數部分之外,還可以使用以下轉換器構建規則: 轉換器 | 描述 -------- | ----- string | (預設值) 接受任何不包含斜槓的文字 int | 接受正整數 float |接受正浮點數 path | 類似 string ,但可以包含斜槓 uuid | 接受 UUID 字串 ```python #!/usr/bin/python # -*- coding: UTF-8 -*- """ @author:chenshifeng @file:flask_demo.py @time:2021/03/01 """ from flask import Flask app = Flask(__name__) @app.route('/post/') def show_post(post_id): # show the post with the given id, the id is an integer return 'Post %d' % post_id @app.route('/path/') def show_subpath(subpath): # show the subpath after /path/ return 'Subpath %s' % subpath if __name__ == '__main__': app.run(debug=True) ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302000959798.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302001044137.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) ## 4.1唯一的 URL / 重定向行為 以下兩條規則的不同之處在於是否使用尾部的斜槓。: ```python @app.route('/projects/') def projects(): return 'The project page' @app.route('/about') def about(): return 'The about page' ``` projects 的 URL 是中規中矩的,尾部有一個斜槓,看起來就如同一個資料夾。 訪問一個沒有斜槓結尾的 URL 時 Flask 會自動進行重定向,幫你在尾部加上一個斜槓。 about 的 URL 沒有尾部斜槓,因此其行為表現與一個檔案類似。如果訪問這個 URL 時添加了尾部斜槓就會得到一個 404 錯誤。這樣可以保持 URL 唯一,並幫助 搜尋引擎避免重複索引同一頁面。 # 5.Flask URL構建 url_for()函式對於動態構建特定函式的URL非常有用。該函式接受函式的名稱作為第一個引數,以及一個或多個關鍵字引數,每個引數對應於URL的變數部分。 ```python #!/usr/bin/python # -*- coding: UTF-8 -*- """ @author:chenshifeng @file:flask_demo.py @time:2021/03/01 """ from flask import Flask, redirect, url_for app = Flask(__name__) @app.route('/admin') def hello_admin(): return 'Hello Admin' @app.route('/guest/') def hello_guest(guest): return 'Hello %s as Guest' % guest @app.route('/user/') def hello_user(name): if name == 'admin': return redirect(url_for('hello_admin')) else: return redirect(url_for('hello_guest', guest=name)) if __name__ == '__main__': app.run(debug=True) ``` >redirect函式用於重定向,實現機制很簡單,就是向客戶端(瀏覽器)傳送一個重定向的HTTP報文,瀏覽器會去訪問報文中指定的url。 執行 開啟瀏覽器並輸入URL - [http://localhost:5000/user/admin](http://localhost:5000/user/admin) ```python Hello Admin ``` 在瀏覽器中輸入以下URL - [http://localhost:5000/user/mvl](http://localhost:5000/user/mvl) ```python Hello mvl as Guest ``` # 6.Flask HTTP方法 Web 應用使用不同的 HTTP 方法處理 URL 。當你使用 Flask 時,應當熟悉 HTTP 方法。 預設情況下,一個路由只回應 GET 請求。 可以使用 route() 裝飾器的 methods 引數來處理不同的 HTTP 方法: 方法 |描述 --|-- GET|以未加密的形式將資料傳送到伺服器,最常見的方法。 HEAD|和GET方法相同,但沒有響應體。 POST|用於將HTML表單資料傳送到伺服器,POST方法接收的資料不由伺服器快取。 PUT|用上傳的內容替換目標資源的所有當前表示。 DELETE|刪除由URL給出的目標資源的所有當前表示。 預設情況下,Flask路由響應GET請求。但是,可以通過為route()裝飾器提供方法引數來更改此首選項。 為了演示在URL路由中使用POST方法,首先讓我們建立一個HTML表單,並使用POST方法將表單資料傳送到URL。 將以下指令碼另存為login.html ```html

Enter Name:

``` 執行以下程式碼 ```python from flask import Flask, redirect, url_for, request app = Flask(__name__) @app.route('/success/') def success(name): return 'welcome %s' % name @app.route('/login',methods = ['POST', 'GET']) def login(): if request.method == 'POST': user = request.form['nm'] return redirect(url_for('success',name = user)) else: user = request.args.get('nm') return redirect(url_for('success',name = user)) if __name__ == '__main__': app.run(debug = True) ``` 在瀏覽器中開啟login.html,在文字欄位中輸入name,然後單擊提交。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302005339399.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 表單資料將POST到表單標籤的action子句中的URL。 http://localhost/login對映到login()函式。由於伺服器通過POST方法接收資料,因此通過以下步驟獲得從表單資料獲得的“nm”引數的值: 表單資料將POST到表單標籤的action子句中的URL。 ```python user = request.form['nm'] ``` 它作為變數部分傳遞給'/ success' URL。瀏覽器在視窗中顯示welcome訊息。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302005628938.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 在login.html中將方法引數更改為'GET',然後在瀏覽器中再次開啟它。伺服器上接收的資料是通過GET方法獲得的。通過以下的步驟獲得'nm'引數的值: ```python User = request.args.get('nm') ``` 這裡,args是包含表單引數對及其對應值對的列表的字典物件。與'nm'引數對應的值將像之前一樣傳遞到'/ success' URL。 # 7.Flask 模板 在大型應用中,把業務邏輯和表現內容放在一起,會增加程式碼的複雜度和維護成本. - 模板其實是一個包含響應文字的檔案,其中用佔位符(變數)表示動態部分,告訴模板引擎其具體的值需要從使用的資料中獲取 - 使用真實值替換變數,再返回最終得到的字串,這個過程稱為'渲染' - Flask 是使用 Jinja2 這個模板引擎來渲染模板 使用模板的好處 - 檢視函式只負責業務邏輯和資料處理(業務邏輯方面) - 而模板則取到檢視函式的資料結果進行展示(檢視展示方面) - 程式碼結構清晰,耦合度低 使用 render_template() 方法可以渲染模板,你只要提供模板名稱和需要 作為引數傳遞給模板的變數就行了。 Flask 會在 templates 資料夾內尋找模板。因此,如果你的應用是一個模組, 那麼模板資料夾應該在模組旁邊;如果是一個包,那麼就應該在包裡面: 情形 1 : 一個模組: ```python /application.py /templates /hello.html ``` 情形 2 : 一個包: ```python /application /__init__.py /templates /hello.html ``` 示例程式碼: ```python from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): my_int = 18 my_str = 'curry' my_list = [1, 5, 4, 3, 2] my_dict = { 'name': 'durant', 'age': 28 } # render_template方法:渲染模板 # 引數1: 模板名稱 引數n: 傳到模板裡的資料 return render_template('hello.html', my_int=my_int, my_str=my_str, my_list=my_list, my_dict=my_dict) if __name__ == '__main__': app.run(debug=True) ``` ```html Title

我是模板

{{ my_int }}
{{ my_str }}
{{ my_list }}
{{ my_dict }}

模板的list資料獲取


{{ my_list[0] }}
{{ my_list.1 }}

字典資料獲取


{{ my_dict['name'] }}
{{ my_dict.age }}

算術運算


{{ my_list.0 + 10 }}
{{ my_list[0] + my_list.1 }} ``` 執行效果: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302214111113.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) # 8.Flask 靜態檔案 動態的 web 應用也需要靜態檔案,一般是 CSS 和 JavaScript 檔案。理想情況下你的 伺服器已經配置好了為你的提供靜態檔案的服務。但是在開發過程中, Flask 也能做好 這項工作。只要在你的包或模組旁邊建立一個名為 static 的資料夾就行了。 靜態檔案位於應用的 /static 中。 使用特定的 'static' 端點就可以生成相應的 URL ```python url_for('static', filename='style.css') ``` >
這個靜態檔案在檔案系統中的位置應該是 static/style.css 。 在下面的示例中,在index.html中的HTML按鈕的OnClick事件上呼叫hello.js中定義的javascript函式,該函式在Flask應用程式的“/”URL上呈現。 ```python from flask import Flask, render_template app = Flask(__name__) @app.route("/") def index(): return render_template("index.html") if __name__ == '__main__': app.run(debug = True) ``` index.html的HTML指令碼如下所示: ```html ``` Hello.js包含sayHello()函式。 ```javascript function sayHello() { alert("Hello World") } ``` 執行效果: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302215153793.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) # 9.Flask Request物件 來自客戶端網頁的資料作為全域性請求物件傳送到伺服器。為了處理請求資料,應該從Flask模組匯入。 Request物件的重要屬性如下所列: - form - 它是一個字典物件,包含表單引數及其值的鍵和值對。 - args - 解析查詢字串的內容,它是問號(?)之後的URL的一部分。 - Cookies - 儲存Cookie名稱和值的字典物件。 - files - 與上傳檔案有關的資料。 - method - 當前請求方法 首先,你必須從 flask 模組匯入請求物件: ```python from flask import request ``` ## 9.1 Flask 將表單資料傳送到模板 我們已經看到,可以在 URL 規則中指定 http 方法。觸發函式接收的 Form 資料可以以字典物件的形式收集它並將其轉發到模板以在相應的網頁上呈現它。 在以下示例中,'/' URL 會呈現具有表單的網頁(student.html)。填入的資料會發布到觸發 result() 函式的 '/result' URL。 result() 函式收集字典物件中的 request.form 中存在的表單資料,並將其傳送給 result.html。 該模板動態呈現表單資料的 HTML 表格。 下面給出的是應用程式的 Python 程式碼: ```python from flask import Flask, render_template, request app = Flask(__name__) @app.route('/') def student(): return render_template('student.html') @app.route('/result',methods = ['POST', 'GET']) def result(): if request.method == 'POST': result = request.form return render_template("result.html",result = result) if __name__ == '__main__': app.run(debug = True) ``` 下面給出的是 student.html 的 HTML 指令碼。 ```html Title

Name

Physics

Chemistry

Maths

``` 下面給出了模板( result.html )的程式碼: ```html {% for key, value in result.items() %} {% endfor %}
{{ key }} {{ value }}
``` 執行效果: 執行 Python 指令碼,並在瀏覽器中輸入 URL http://localhost:5000/。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302221123782.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70)當點選提交按鈕時,表單資料以 HTML 表格的形式呈現在 result.html 上。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302221159872.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) ## 9.2 Flask Cookies Cookie以文字檔案的形式儲存在客戶端的計算機上。其目的是記住和跟蹤與客戶使用相關的資料,以獲得更好的訪問者體驗和網站統計資訊。 Request物件包含Cookie的屬性。它是所有cookie變數及其對應值的字典物件,客戶端已傳輸。除此之外,cookie還儲存其網站的到期時間,路徑和域名。 在Flask中,對cookie的處理步驟為: 1. 設定cookie: 設定cookie,預設有效期是臨時cookie,瀏覽器關閉就失效 可以通過 max_age 設定有效期, 單位是秒 ```python resp = make_response("success") # 設定響應體 resp.set_cookie("chenshifeng", "shifengboy", max_age=3600) ``` 2. 獲取cookie 獲取cookie,通過request.cookies的方式, 返回的是一個字典,可以獲取字典裡的相應的值 ```python cookie_1 = request.cookies.get("chenshifeng") ``` 3. 刪除cookie 這裡的刪除只是讓cookie過期,並不是直接刪除cookie 刪除cookie,通過delete_cookie()的方式, 裡面是cookie的名字 ```python resp = make_response("del success") # 設定響應體 resp.delete_cookie("chenshifeng") ``` 以下為Flask Cookies的簡單示例: ```python from flask import Flask, make_response, request app = Flask(__name__) @app.route("/set_cookies") def set_cookie(): resp = make_response("success") resp.set_cookie("chenshifeng", "shifengboy",max_age=3600) return resp @app.route("/get_cookies") def get_cookie(): cookie_1 = request.cookies.get("chenshifeng") # 獲取名字為Itcast_1對應cookie的值 return cookie_1 @app.route("/delete_cookies") def delete_cookie(): resp = make_response("del success") resp.delete_cookie("chenshifeng") return resp if __name__ == '__main__': app.run(debug=True) ``` 設定cookies 執行應用程式,在瀏覽器中輸入 127.0.0.1:5000/set_cookies 來設定cookies,設定 cookies 的輸出如下所示: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302222517381.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 獲取cookie 根據檢視函式中相對應的路徑,輸入 http://127.0.0.1:5000/get_cookies ,讀回 cookies 的輸出如下所示: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302222857515.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 刪除cookie 根據檢視函式中相對應的路徑,輸入 http://127.0.0.1:5000/delete_cookies ,刪除 cookies 的輸出如下所示: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2021030222311571.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) >注意刪除,只是讓 cookie 過期。 # 10.Flask 會話 與Cookie不同,Session(會話)資料儲存在伺服器上。會話是客戶端登入到伺服器並登出伺服器的時間間隔。需要在該會話中儲存的資料會儲存在伺服器上的臨時目錄中。 為每個客戶端的會話分配會話ID。會話資料儲存在cookie的頂部,伺服器以加密方式對其進行簽名。對於此加密,Flask應用程式需要一個定義的SECRET_KEY。 Session物件也是一個字典物件,包含會話變數和關聯值的鍵值對。 例如,要設定一個'username'會話變數,請使用以下語句: ```python Session['username'] = 'admin' ``` 要釋放會話變數,請使用pop()方法。 ```python session.pop('username', None) ``` 演示程式碼: ```python from flask import Flask, session, redirect, url_for, request app = Flask(__name__) app.secret_key = 'fkdjsafjdkfdlkjfadskjfadskljdsfklj' # 確保設定應用程式的secret_key @app.route('/') def index(): if 'username' in session: username = session['username'] return '登入使用者名稱是:' + username + '
' + \ "點選這裡登出" return "您暫未登入,
" + \ "點選這裡登入" @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('index')) return '''

''' @app.route('/logout') def logout(): # remove the username from the session if it is there session.pop('username', None) return redirect(url_for('index')) if __name__ == '__main__': app.run(debug=True) ``` >如何生成一個好的金鑰 生成隨機數的關鍵在於一個好的隨機種子,因此一個好的金鑰應當有足夠的隨機性。 作業系統可以有多種方式基於密碼隨機生成器來生成隨機資料。使用下面的命令 可以快捷的為 Flask.secret_key ( 或者 SECRET_KEY )生成值: $ python -c 'import os; print(os.urandom(16))' b'_5#y2L"F4Q8z\n\xec]/' 訪問http://127.0.0.1:5000/,只是提示使用者登入,因為未設定會話變數'username'。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302225541698.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 當用戶點選登入,瀏覽到“/login”login()檢視函式時,因為它是通過GET方法呼叫的,所以將開啟一個登入表單。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302225745379.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 點選登入,通過POST方法將表單傳送回'/login',現在會話變數已設定。應用程式重定向到'/'。此時會話變數'username'被找到。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302225821702.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 應用程式還包含一個logout()檢視函式,它會彈出'username'會話變數。因此,'/' URL再次顯示開始頁面。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302225920305.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) # 11.Flask 重定向和錯誤 Flask類有一個redirect()函式。呼叫時,它返回一個響應物件,並將使用者重定向到具有指定狀態程式碼的另一個目標位置。 redirect()函式的原型如下: ```python Flask.redirect(location, statuscode, response) ``` 在上述函式中: - location引數是應該重定向響應的URL。 - statuscode傳送到瀏覽器標頭,預設為302。 - response引數用於例項化響應。 以下狀態程式碼已標準化: - HTTP_300_MULTIPLE_CHOICES - HTTP_301_MOVED_PERMANENTLY - HTTP_302_FOUND - HTTP_303_SEE_OTHER - HTTP_304_NOT_MODIFIED - HTTP_305_USE_PROXY - HTTP_306_RESERVED - HTTP_307_TEMPORARY_REDIRECT 預設狀態程式碼為302,表示'found'。 在以下示例中,redirect()函式用於在登入嘗試失敗時再次顯示登入頁面。 ```python from flask import Flask, redirect, url_for, render_template, request # Initialize the Flask application app = Flask(__name__) @app.route('/') def index(): return render_template('log_in.html') @app.route('/login', methods=['POST', 'GET']) def login(): if request.method == 'POST' and request.form['username'] == 'admin': return redirect(url_for('success')) return redirect(url_for('index')) @app.route('/success') def success(): return 'logged in successfully' if __name__ == '__main__': app.run(debug=True) ``` 下面給出的是 log_in.html的 HTML 指令碼。 ```html Title

Enter Name:

``` Flask類具有帶有錯誤程式碼的abort()函式。 ```python Flask.abort(code) ``` Code引數採用以下值之一: - 400 - 用於錯誤請求 - 401 - 用於未身份驗證的 - 403 - Forbidden - 404 - 未找到 - 406 - 表示不接受 - 415 - 用於不支援的媒體型別 - 429 - 請求過多 讓我們對上述程式碼中的login()函式稍作更改。如果要顯示'Unauthurized'頁面,請將其替換為呼叫abort(401),而不是重新顯示登入頁面。 ```python from flask import Flask, redirect, url_for, render_template, request, abort app = Flask(__name__) @app.route('/') def index(): return render_template('log_in.html') @app.route('/login', methods=['POST', 'GET']) def login(): if request.method == 'POST': if request.form['username'] == 'admin': return redirect(url_for('success')) else: abort(401) else: return redirect(url_for('index')) @app.route('/success') def success(): return 'logged in successfully' if __name__ == '__main__': app.run(debug=True) ``` 執行,輸入非admin的使用者名稱,點選提交 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210302234932861.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) # 12. Flask 訊息閃現 一個好的基於 GUI 的應用程式會向用戶提供有關互動的反饋。例如,桌面應用程式使用對話方塊或訊息框,JavaScript 使用警報用於類似目的。 在 Flask Web 應用程式中生成這樣的資訊性訊息很容易。Flask 框架的閃現系統可以在一個檢視中建立訊息,並在名為 next 的檢視函式中呈現它。 Flask 模組包含 flash() 方法。它將訊息傳遞給下一個請求,該請求通常是一個模板。 ```python flash(message, category) ``` 其中, - message 引數是要閃現的實際訊息。 - category 引數是可選的。它可以是“error”,“info”或“warning”。 為了從會話中獲取訊息,模板呼叫 get_flashed_messages()。 以下是一個完整的示例: ```python from flask import Flask, flash, redirect, render_template, \ request, url_for app = Flask(__name__) app.secret_key = b'_5#y2L"F4Q8z\n\xec]/' @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') return redirect(url_for('index')) return render_template('login.html', error=error) if __name__ == '__main__': app.run(debug=True) ``` 以下是實現閃現的 layout.html 模板: ```html My Application {% with messages = get_flashed_messages() %} {% if messages %}
    {% for message in messages %}
  • {{ message }}
  • {% endfor %}
{% endif %} {% endwith %} {% block body %}{% endblock %} ``` 以下是繼承自 layout.html 的 index.html 模板: ```html {% block body %}

Overview

Do you want to log in? {% endblock %} ``` 以下是同樣繼承自 layout.html 的 login.html 模板: ```html {% extends "layout.html" %} {% block body %}

Login

{% if error %}

Error: {{ error }} {% endif %}

Username:
Password:

{% endblock %} ``` 執行 首頁 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210304232856405.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 登入報錯頁 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210304232923228.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 登入成功頁 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210304232958742.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) # 13. Flask 檔案上傳 在 Flask 中處理檔案上傳非常簡單。它需要一個 HTML 表單,其 ​`enctype​ `屬性設定為`'multipart/form-data​'`,將檔案釋出到 URL。URL 處理程式從 ​`request.files[]​ `物件中提取檔案,並將其儲存到所需的位置。 每個上傳的檔案首先會儲存在伺服器上的臨時位置,然後將其實際儲存到它的最終位置。目標檔案的名稱可以是硬編碼的,也可以從 ​`request.files[file] `​物件的​` filename `​屬性中獲取。但是,建議使用 ​`secure_filename()​ `函式獲取它的安全版本。 可以在 Flask 物件的配置設定中定義預設上傳資料夾的路徑和上傳檔案的最大大小。 >app.config[‘UPLOAD_FOLDER’] 定義上傳資料夾的路徑 app.config[‘MAX_CONTENT_LENGTH’] 指定要上傳的檔案的最大大小(以位元組為單位) 以下程式碼具有 `​'/upload'` ​URL 規則,該規則在 templates 資料夾中顯示​ `'upload.html'​`,以及 `​'/ upload-file' `​URL 規則,用於呼叫 `​uploader() ​`函式處理上傳過程。 `​'upload.html'` ​有一個檔案選擇器按鈕和一個提交按鈕。 ```html File Upload ``` 以下是 Flask 應用程式的 Python 程式碼。 ```python from flask import Flask, render_template, request from werkzeug.utils import secure_filename import os app = Flask(__name__) app.config['UPLOAD_FOLDER'] = '/Users/chenshifeng/upload/' @app.route('/upload') def upload_file(): return render_template('upload.html') @app.route('/uploader', methods = ['GET', 'POST']) def uploader(): if request.method == 'POST': f = request.files['file'] f.save(os.path.join(app.config['UPLOAD_FOLDER'],secure_filename(f.filename))) return 'file uploaded successfully' if __name__ == '__main__': app.run() ``` 您將看到如下所示的介面。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210303223915144.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 選擇檔案後,單擊提交。表單的​ post ​方法呼叫​ `'/ upload_file'​ `URL。底層函式 `​uploader()​ `執行儲存操作。 上傳成功會顯示以下畫面: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210303225030430.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 上傳檔案被放到/Users/chenshifeng/upload資料夾下: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210303225234621.png) # 14. Flask 擴充套件 Flask通常被稱為微框架,因為核心功能包括基於Werkzeug的WSGI和路由以及基於Jinja2的模板引擎。此外,Flask框架還支援cookie和會話,以及JSON,靜態檔案等Web幫助程式。顯然,這不足以開發完整的Web應用程式。而Flask擴充套件就具備這樣的功能。Flask擴充套件為Flask框架提供了可擴充套件性。 有大量的Flask擴充套件可用。Flask擴充套件是一個Python模組,它向Flask應用程式添加了特定型別的支援。Flask Extension Registry(Flask擴充套件登錄檔)是一個可用的擴充套件目錄。可以通過pip實用程式下載所需的副檔名。 在本教程中,我們將討論以下重要的Flask擴充套件: - Flask Mail - 為Flask應用程式提供SMTP介面 - Flask WTF - 新增WTForms的渲染和驗證 - Flask SQLAlchemy - 為Flask應用程式新增SQLAlchemy支援 - Flask Sijax - Sijax的介面 - Python/jQuery庫,使AJAX易於在Web應用程式中使用 每種型別的擴充套件通常提供有關其用法的大量文件。由於擴充套件是一個Python模組,因此需要匯入它才能使用它。Flask副檔名通常命名為flask-foo。匯入的操作如下: ```python from flask_foo import [class, function] ``` 對於0.7以後的Flask版本,您還可以使用語法: ```python from flask.ext import foo ``` 對於此用法,需要啟用相容性模組。它可以通過執行flaskext_compat.py來安裝: ```python import flaskext_compat flaskext_compat.activate() from flask.ext import foo ``` ## 14.1 Flask 郵件 務器建立簡單的介面變得非常容易。 首先,應該在pip實用程式的幫助下安裝Flask-Mail擴充套件。 ```python pip install Flask-Mail ``` 然後需要通過設定以下應用程式引數的值來配置Flask-Mail。 引數|描述 --|-- MAIL_SERVER|電子郵件伺服器的名稱/IP地址 MAIL_PORT|使用的伺服器的埠號 MAIL_USE_TLS|啟用/禁用傳輸安全層加密 MAIL_USE_SSL|啟用/禁用安全套接字層加密 MAIL_DEBUG|除錯支援。預設值是Flask應用程式的除錯狀態 MAIL_USERNAME|發件人的使用者名稱 MAIL_PASSWORD|發件人的密碼 MAIL_DEFAULT_SENDER|設定預設發件人 MAIL_MAX_EMAILS|設定要傳送的最大郵件數 MAIL_SUPPRESS_SEND|如果app.testing設定為true,則傳送被抑制 MAIL_ASCII_ATTACHMENTS|如果設定為true,則附加的檔名將轉換為ASCII flask-mail模組包含以下重要類的定義。 ### 14.1.1 Mail類 它管理電子郵件訊息傳遞需求。類建構函式採用以下形式: ```python flask-mail.Mail(app = None) ``` 建構函式將Flask應用程式物件作為引數。 Mail類的方法: 方法|描述 --|-- send()|傳送Message類物件的內容 connect()|開啟與郵件主機的連線 send_message()|傳送訊息物件 ### 14.1.2 Message類 它封裝了一封電子郵件。Message類建構函式有幾個引數: ```python flask-mail.Message(subject, recipients, body, html, sender, cc, bcc, reply-to, date, charset, extra_headers, mail_options,rcpt_options) ``` Message類方法: - attach() - 為郵件新增附件。此方法採用以下引數: - filename - 要附加的檔案的名稱 - content_type - MIME型別的檔案 - data - 原始檔案資料 - 處置 - 內容處置(如果有的話)。 - add_recipient() - 向郵件新增另一個收件人 在下面的示例中,使用QQ郵箱服務的SMTP伺服器用作Flask-Mail配置的MAIL_SERVER。 ```python from flask import Flask from flask_mail import Mail, Message app =Flask(__name__) mail=Mail(app) app.config['MAIL_SERVER']='smtp.qq.com' app.config['MAIL_PORT'] = 465 app.config['MAIL_USERNAME'] = '[email protected]' app.config['MAIL_PASSWORD'] = 'xxxxxxxx' app.config['MAIL_USE_TLS'] = False app.config['MAIL_USE_SSL'] = True mail = Mail(app) @app.route("/") def index(): msg = Message('Hello', sender = '[email protected]', recipients = ['[email protected]']) msg.body = "Hello Flask message sent from Flask-Mail" mail.send(msg) return "Sent" if __name__ == '__main__': app.run(debug = True) ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210303233231923.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) # 15. Flask SQLAlchemy 步驟1 - 安裝Flask-SQLAlchemy擴充套件。 ```python pip install flask-sqlalchemy ``` 步驟2 - 您需要從此模組匯入SQLAlchemy類。 ```python from flask_sqlalchemy import SQLAlchemy ``` 步驟3 - 現在建立一個Flask應用程式物件併為要使用的資料庫設定URI。 ```python app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.sqlite3' ``` 步驟4 - 然後使用應用程式物件作為引數建立SQLAlchemy類的物件。該物件包含用於ORM操作的輔助函式。它還提供了一個父Model類,使用它來宣告使用者定義的模型。在下面的程式碼段中,建立了students模型。 ```python db = SQLAlchemy(app) class students(db.Model): id = db.Column('student_id', db.Integer, primary_key = True) name = db.Column(db.String(100)) city = db.Column(db.String(50)) addr = db.Column(db.String(200)) pin = db.Column(db.String(10)) def __init__(self, name, city, addr,pin): self.name = name self.city = city self.addr = addr self.pin = pin ``` 步驟5 - 要建立/使用URI中提及的資料庫,請執行create_all()方法。 ```python db.create_all() ``` SQLAlchemy的Session物件管理ORM物件的所有永續性操作。 以下session方法執行CRUD操作: - db.session.add (模型物件) - 將記錄插入到對映表中 - db.session.delete (模型物件) - 從表中刪除記錄 - model.query.all() - 從表中檢索所有記錄(對應於SELECT查詢)。 您可以通過使用filter屬性將過濾器應用於檢索到的記錄集。例如,要在學生表中檢索city ='Hyderabad'的記錄,請使用以下語句: ```python Students.query.filter_by(city = ’Hyderabad’).all() ``` 有了這麼多的背景,現在我們將為我們的應用程式提供檢視函式來新增學生資料。 應用程式的入口點是繫結到'/' URL的show_all()函式。學生表的記錄集作為引數傳送到HTML模板。模板中的伺服器端程式碼以HTML表格形式呈現記錄。 ```python @app.route('/') def show_all(): return render_template('show_all.html', students = students.query.all() ) ``` 模板('show_all.html')的HTML指令碼如下: ```html

Comments - Flask SQLAlchemy example


{%- for message in get_flashed_messages() %} {{ message }} {%- endfor %}

Students (Add Student )

{% for student in students %} {% endfor %}
Name City Address Pin
{{ student.name }} {{ student.city }} {{ student.addr }} {{ student.pin }}
``` 上述網頁包含指向'/ new' URL對映new()函式的超連結。單擊時,將開啟“學生資訊”表單。 資料在 POST方法中釋出到相同的URL。 new.html ```html

Students - Flask SQLAlchemy example


{%- for category, message in get_flashed_messages(with_categories = true) %} {{ message }} {%- endfor %}







``` 當http方法被檢測為POST時,表單資料被新增到學生表中,並且應用返回到顯示新增資料的主頁。 ```python @app.route('/new', methods = ['GET', 'POST']) def new(): if request.method == 'POST': if not request.form['name'] or not request.form['city'] or not request.form['addr']: flash('Please enter all the fields', 'error') else: student = students(request.form['name'], request.form['city'], request.form['addr'], request.form['pin']) db.session.add(student) db.session.commit() flash('Record was successfully added') return redirect(url_for('show_all')) return render_template('new.html') ``` 下面給出了應用程式(app.py)的完整程式碼。 ```python from flask import Flask, request, flash, url_for, redirect, render_template from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.sqlite3' app.config['SECRET_KEY'] = "random string" db = SQLAlchemy(app) class students(db.Model): id = db.Column('student_id', db.Integer, primary_key=True) name = db.Column(db.String(100)) city = db.Column(db.String(50)) addr = db.Column(db.String(200)) pin = db.Column(db.String(10)) def __init__(self, name, city, addr, pin): self.name = name self.city = city self.addr = addr self.pin = pin @app.route('/') def show_all(): return render_template('show_all.html', students=students.query.all()) @app.route('/new', methods=['GET', 'POST']) def new(): if request.method == 'POST': if not request.form['name'] or not request.form['city'] or not request.form['addr']: flash('Please enter all the fields', 'error') else: student = students(request.form['name'], request.form['city'], request.form['addr'], request.form['pin']) db.session.add(student) db.session.commit() flash('Record was successfully added') return redirect(url_for('show_all')) return render_template('new.html') if __name__ == '__main__': db.create_all() app.run(debug=True) ``` 首頁 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210304232415161.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 錯誤頁: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2021030423243585.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 提交成功頁: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210304232517206.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoaWZlbmdib3k=,size_16,color_FFFFFF,t_70) 本文參考:https://www.w3cschool.cn