前言
Python Web框架里比較有名當屬Django,Django功能全面,它提供一站式解決方案,集成了MVT(Model-View-Template)和ORM,以及后臺管理。但是缺點也很明顯,它偏重。就像是一個裝潢好的房子,它提供好了你要用的東西,直接拿來用就可以。
Flask相對于Django而言是輕量級的Web框架。和Django不同,Flask輕巧、簡潔,通過定制第三方擴展來實現具體功能。
可定制性,通過擴展增加其功能,這是Flask最重要的特點。Flask的兩個主要核心應用是Werkzeug和模板引擎Jinja。

WSGI
Web Server Gateway Interface(Web服務器網關接口,WSGI)已被用作Python Web應用程序開發的標準。 WSGI是Web服務器和Web應用程序之間通用接口的規范。
Werkzeug
它是一個WSGI工具包,它實現了請求,響應對象和實用函數。這使得能夠在其上構建web框架。 Flask框架使用Werkzeug作為其基礎之一。
jinja2
jinja2是Python的一個流行的模板引擎。Web模板系統將模板與特定數據源組合以呈現動態網頁。
Flask通常被稱為微框架。 它旨在保持應用程序的核心簡單且可擴展。Flask沒有用于數據庫處理的內置抽象層,也沒有形成驗證支持。相反,Flask支持擴展以向應用程序添加此類功能。一些受歡迎的Flask擴展將在本教程后續章節進行討論。
Flask工作流程圖

Flask擴展包:
- Flask-SQLalchemy:操作數據庫
- Flask-migrate:管理遷移數據庫
- Flask-Mail:郵件
- Flask-WTF:表單
- Flask-script:插入腳本
- Flask-Login:認證用戶狀態
- Flask-RESTful:開發REST API的工具
- Flask-Bootstrap:集成前端Twitter Bootstrap框架
- Flask-Moment:本地化日期和時間
新建flask項目:

建成如下:

運行如下:

必須在項目中導入Flask模塊。 Flask類的一個對象是我們的WSGI應用程序。
Flask構造函數使用當前模塊(__name __)的名稱作為參數。
以下是實例化一個Flask對象可填的參數,及其默認值:
- template_folder:模板所在文件夾的名字, 默認就是templates
- root_path:可以不用填,會自動找到,當前執行文件,所在目錄地址在return render_template時會將上面兩個進行拼接,找到對應的模板地址
- static_folder:靜態文件所在文件的名字,默認是static,可以不用填
- static_url_path:靜態文件的地址前綴,寫成什么,訪問靜態文件時,就要在前面加上這個
instance_path和instance_relative_config是配合來用的、這兩個參數是用來找配置文件的,當用App.config.from_pyfile('settings.py')這種方式導入配置文件的時候會用到
- instance_relative_config:默認為False,當設置為True時,from_pyfile會從instance_path指定的地址下查找文件。
- instsnce_path:指定from_pyfile查詢文件的路徑,不設置時,默認尋找和app.run()的執行文件同級目錄下的instance文件夾,如果配置了instance_path(注意需要是絕對路徑),就會從指定的地址下里面的文件
Flask類的route()函數是一個裝飾器,它告訴應用程序哪個URL應該調用相關的函數。
app.route(rule, options)
- rule 參數表示與該函數的URL綁定。
- options 是要轉發給基礎Rule對象的參數列表。
在上面的示例中,'/ ' URL與hello_world()函數綁定。因此,當在瀏覽器中打開web服務器的主頁時,將呈現該函數的輸出。
application對象的add_url_rule()函數也可用于將URL與函數綁定,如下:
def hello_world():
return ‘hello world’
app.add_url_rule(‘/’, ‘hello’,hello_world)
最后,Flask類的run()方法在本地開發服務器上運行應用程序。
app.run(host, port, debug, options)
- host:監聽的主機名
- post:監聽的主機端口,默認5000
- debug:調試模式,默認false,設置為frue則顯示調試信息
- options:要轉發到底層的werkzeng服務器
給路由傳參示例:
from flask importFlask
app = Flask(__name__)
@app.route('/id/<int:idn>')def hello_world(idn):
return 'HelloWorld! %d' %idn
if __name__ == '__main__':
app.run()
路由傳遞的參數默認當做string處理,這里指定int,還支持float,path,尖括號中冒號后面的內容是動態的。
效果如下:

返回狀態碼示例:

abort函數:
如果在視圖函數執行過程中,出現了異常錯誤,我們可以使用abort函數立即終止視圖函數的執行。通過abort函數,可以向前端返回一個http標準中存在的錯誤狀態碼,表示出現的錯誤信息。
使用abort拋出一個http標準中不存在的自定義的狀態碼,沒有實際意義。如果abort函數被觸發,其后面的語句將不會執行。其類似于python中raise。
from flask importFlask,abort
app = Flask(__name__)
@app.route('/id/<int:idn>')def hello_world(idn):
abort(403)
return 'HelloWorld! %d' %idn, 888
if __name__ == '__main__':
app.run()
在Flask中通過裝飾器來實現捕獲異常,errorhandler()接收的參數為異常狀態碼。視圖函數的參數,返回的是錯誤信息。

重定向redirect示例:
from flask importFlask,redirect
app = Flask(__name__)
@app.route('/')def hello_world():
return redirect('https://www.baidu.com')
if __name__ == '__main__':
app.run()
效果如下:

這里再介紹一下url_for(),url_for()函數對于動態構建特定函數的URL非常有用。該函數接受函數的名稱作為第一個參數,以及一個或多個關鍵字參數,每個參數對應于URL的變量部分。
如下:
@app.route('/user/<name>')def hello_user(name):
if name=='admin':
return redirect(url_for('hello_admin'))
else:
return redirect(url_for('hello_guest',guest =name))
HTTP方法:
Http協議是萬維網中數據通信的基礎。在該協議中定義了從指定URL檢索數據的不同方法。
方法介紹:
- GET:以未加密的形式將數據發送到服務器獲取響應內容
- POST: 用于將html表單數據上傳到服務器
- PUT:用上傳的內容替換目標資源的數據
- DELETE:刪除由URL給出的目標資源的數據
- HEAD: 和GET方法相同,但沒響應體
默認情況下,Flask路由響應GET請求。但是,可以通過為route()裝飾器提供方法參數來更改此首選項。
為了演示在URL路由中使用POST方法,首先讓我們創建一個HTML表單,并使用POST方法將表單數據發送到URL。
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action = "http://localhost:5000/login"method = "post">
<p>Enter Name:</p>
<p><input type = "text" name = "nm"/></p>
<p><input type = "submit" value = "submit"/></p>
</form>
</body>
</html>
loginok.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello {{ name }}</h1>
</body>
</html>
WC_public_flask.py
from flask importFlask, render_template, request
app = Flask(__name__, template_folder='templates')
@app.route('/')def login():
return render_template('login.html')
@app.route('/login',methods = ['POST', 'GET'])def loginok():
if request.method== 'POST':
user = request.form['nm']
return render_template('loginok.html',name =user)
else:
user = request.args.get('nm')
return render_template('loginok.html',name =user)
if __name__ == '__main__':
app.run(debug = True)