Flask誕生於2010年,是Armin ronacher(人名)用 Python 語言基於 Werkzeug 工具箱編寫的輕量級Web開發框架。
Flask 本身相當於一個內核,其他幾乎所有的功能都要用到擴展(郵件擴展Flask-Mail,用戶認證Flask-Login,數據庫Flask-SQLAlchemy),都需要用第三方的擴展來實現。比如可以用 Flask 擴展加入ORM、窗體驗證工具,文件上傳、身份驗證等。Flask 沒有默認使用的數據庫,你可以選擇 MySQL,也可以用 NoSQL。其 WSGI 工具箱采用 Werkzeug(路由模塊),模板引擎則使用 Jinja2。這兩個也是 Flask 框架的核心。
准備
mkvirtualenv flask_demo -p python3
安裝
pip install flask==0.12.4
一 .創建Flask項目
Flask不同於Django,不會提供任何自動的操作,所以需要手動創建項目目錄,需要手動創建啟動項目的管理文件
例如,創建項目目錄flaskdemo,在目錄中創建manage.py。在pycharm中打開項目並指定上面創建的虛擬環境
1 form flask import Flask 2 app = Flask(__name__) 3 4 @app.route('/') 5 def index(): 6 return 'Hello World' 7 8 if __name__ == '__main__': 9 app.run
代碼分析:
1 #導入Flask類 2 3 """ 4 import_name Flask程序所在的包(模塊),傳 __name__ 就可以 5 其可以決定 Flask 在訪問靜態文件時查找的路徑 6 static_path 靜態文件訪問路徑(不推薦使用,使用 static_url_path 代替) 7 static_url_path 靜態文件訪問路徑,可以不傳,默認為:/ + static_folder 8 static_folder 靜態文件存儲的文件夾,可以不傳,默認為 static 9 template_folder 模板文件存儲的文件夾,可以不傳,默認為 templates 10 11 """ 12 app = Flask(__name__)
1 #加載項目配置 2 #配置類 3 class Config(object) 4 DEBUG = True 5 SECRET_KEY = "aaabbbbbddddeeeeb" 6 7 app.config.from_object(Config) 8 9 10 11 12 #指定服務器IP和端口 13 app.run(host="0.0.0.0",port=5000,debug = True)
二.路由的基本定義
1 #指定訪問路徑為demo1 2 @app.route('/demo1') 3 def demo1(): 4 return 'demo1'
路由可以設置傳遞參數,2種方式
1 # 路由傳遞參數[沒有限定類型] 2 @app.route('/user/<user_id>') 3 def user_info(user_id): 4 return 'hello %s' % user_id 5 6 7 # 路由傳遞參數[限定數據類型] 8 @app.route('/user/<int:user_id>') 9 def user_info(user_id): 10 return 'hello %d' % user_id
路由限定請求方式
1 def demo2(): 2 # 直接從請求中取到請求方式並返回 3 return request.method
三.正則匹配路由
在 web 開發中,可能會出現限制用戶訪問規則的場景,那么這個時候就需要用到正則匹配,根據自己的規則去限定請求參數再進行訪問
具體實現步驟為:
- 導入轉換器基類:在 Flask 中,所有的路由的匹配規則都是使用轉換器對象進行記錄
- 自定義轉換器:自定義類繼承於轉換器基類
- 添加轉換器到默認的轉換器字典中
- 使用自定義轉換器實現自定義匹配規則
四.代碼實現
> 導入轉換器基類
from werkzeug.routing import BaseConverter
> 自定義轉換器
1 # 自定義正則轉換器 2 from werkzeug.routing import BaseConverter 3 class RegexConverter(BaseConverter): 4 def __init__(self,url_map,*args): 5 super(RegexConverter, self).__init__(url_map) 6 # 正則參數 7 self.regex = args[0]
> 添加轉換器到默認的轉換器字典中,並指定轉換器使用時名字為: re
1 # 將自定義轉換器添加到轉換器字典中,並指定轉換器使用時名字為: re 2 app.url_map.converters['re'] = RegexConverter
> 使用轉換器去實現自定義匹配規則
>> 當前此處定義的規則是 :手機號
1 # 正則匹配路由 2 @app.route("/login/<re('1\d{10}'):mobile>") 3 def login(mobile): 4 return mobile
五.系統自帶轉換器
1 DEFAULT_CONVERTERS = { 2 'default': UnicodeConverter, 3 'path': PathConverter, 4 'string': UnicodeConverter, 5 'any': AnyConverter, 6 'int': IntegerConverter, 7 'float': FloatConverter, 8 'uuid': UUIDConverter, 9 }
系統自帶的轉換器具體使用方式在每種轉換器的注釋代碼中有寫,請留意每種轉換器初始化的參數。
1 from flask import Flask 2 # 新增一個配置文件,在配置文件中設置配置信息 3 from config import Config 4 from flask import request 5 # from collections import OrderedDict # 有序字典 6 7 app = Flask(__name__) 8 9 # 調用app.config加載配置 10 app.config.from_object(Config) 11 12 13 from werkzeug.routing import BaseConverter 14 15 class RegexConverter(BaseConverter): 16 def __init__(self,url_map,*args): 17 super(RegexConverter, self).__init__(url_map) 18 # 正則參數 19 self.regex = args[0] 20 21 # converter["路由轉換器名稱"] = 實現路由轉換功能的自定義類 22 app.url_map.converters['re'] = RegexConverter 23 # 綁定路由 24 @app.route("/") 25 def index(): 26 return "hello flask" 27 28 29 # 默認情況下,路由使用的就是關鍵字參數,也叫"命名路由" 30 # router(路由地址, http請求方式 ) 31 @app.route("/list/<int:page>/<string:content>",methods=["GET","POST"]) 32 def mylist(content,page): 33 return "第%s頁<br>內容:%s" % (page,content) 34 35 # 正則匹配路由 36 @app.route("/login/<re('1\d{10}'):mobile>") 37 def login(mobile): 38 return mobile
六.Http的請求與響應
> 請求
.request: flask中代表當前請求的 request對象
.作用: 在視圖函數中取出本次請求數據
.導入: from flask import request
常用的屬性如下:
屬性 | 說明 | 類型 |
---|---|---|
data | 記錄請求的數據,並轉換為字符串 | * |
form | 記錄請求中的表單數據 | MultiDict |
args | 記錄請求中的查詢參數 | MultiDict |
cookies | 記錄請求中的cookie信息 | Dict |
headers | 記錄請求中的請求頭 | EnvironHeaders |
method | 記錄請求使用的HTTP方法 | GET/POST |
url | 記錄請求的URL地址 | string |
files | 記錄請求上傳的文件 | * |
json | 記錄請求的json數據 | json |
獲取請求中查詢字符串
http://127.0.0.1:5000/demo1?a=10

1 """獲取客戶端的請求""" 2 @app.route("/request") 3 def req1(): 4 """獲取查詢字符串""" 5 query_string = request.args 6 print(query_string) 7 # 瀏覽器輸入 http://127.0.0.1:5000/request?a=1&b=2 8 """打印效果: ImmutableMultiDict([('a', '1'), ('b', '2')])""" 9 10 # 獲取一個參數的一個值 11 http://127.0.0.1:5000/request?username=abcd 12 username = request.args.get("username") 13 # print(username) 14 """打印效果: abcd """ 15 16 # 獲取一個參數的多個值 17 # http://127.0.0.1:5000/request?username=xiaoming&love=吹牛&love=睡覺 18 love = request.args.getlist("love") 19 # print(love) 20 """打印效果: ['吹牛', '睡覺']""" 21 22 23 # 把傳遞過來的數據抓換成原生的字典 24 data = request.args.to_dict() 25 # print(data) 26 """打印效果:{'username': 'xiaoming', 'love': '吹牛'} """ 27 28 return "ok" 29 30 @app.route("/request2",methods=["POST"]) 31 def req2(): 32 """獲取post數據和請求頭""" 33 # 必須傳 json 格式的數據 34 # print( request.data ) 35 # """打印結果: 36 # b'{\n\t"username":"xiaoming",\n\t"age":18,\n\t"sex":1\n}' 37 # """ 38 # 方式一 39 # import json 40 # from flask import json 41 # data = json.loads(request.data) 42 # print(data) 43 # """打印結果: 44 # {'username': 'xiaoming', 'age': 18, 'sex': 1} 45 #方式二 46 print(request.json) 47 # """打印結果: 48 # {'username': 'xiaoming', 'age': 18, 'sex': 1} 49 # """ 50 # 51 # """獲取請求行數據""" 52 # print( request.headers ) 53 # print( request.headers.to_list() ) 54 55 56 """獲取上傳文件""" 57 print( request.files ) 58 print( request.files.get("avatar") ) 59 """打印效果: 60 ImmutableMultiDict([('avatar', <FileStorage: 'avatar.png' ('image/png')>)]) 61 <FileStorage: 'avatar.png' ('image/png')> 62 """ 63 64 return "ok" 65 66 if __name__ == '__main__': 67 app.run()
響應
flask默認支持2種響應方式:
- 數據響應:
默認響應html文本,也可以返回 JSON格式 - 頁面響應:
重定向 url_for
響應的時候,flask也支持自定義http響應狀態碼
響應html文本
1 @app.route("/") 2 def index(): 3 # [默認支持]響應html文本 4 return "<img src='http://flask.pocoo.org/static/logo.png'>"
返回JSON數據
在 Flask 中可以直接使用 jsonify 生成一個 JSON 的響應
1 from flask import Flask, request, jsonify 2 3 @app.route("/") 4 def index(): 5 # 也可以響應json格式代碼 6 data = [ 7 {"id":1,"username":"liulaoshi","age":18}, 8 {"id":2,"username":"liulaoshi","age":17}, 9 {"id":3,"username":"liulaoshi","age":16}, 10 {"id":4,"username":"liulaoshi","age":15}, 11 ] 12 return jsonify(data)
flask中返回json 數據,都是flask的jsonify方法返回就可以了.
重定向
重定向到百度頁面
1 # 頁面跳轉響應 2 from flask import Flask, request, jsonify, redirect 3 @app.route("/user") 4 def user(): 5 # 頁面跳轉 redirect函數就是response對象的頁面跳轉的封裝 6 # Location: http://www.baidu.com 7 return redirect("http://www.baidu.com")
重定向到自己寫的視圖函數
可以直接填寫自己 url 路徑
也可以使用 url_for 生成指定視圖函數所對應的 url
1 # 內容響應 2 @app.route("/") 3 def index(): 4 # [默認支持]響應html文本 5 # return "<img src='http://flask.pocoo.org/static/logo.png'>" 6 7 # 也可以響應json格式代碼 8 data = [ 9 {"id":1,"username":"liulaoshi","age":18}, 10 {"id":2,"username":"liulaoshi","age":17}, 11 {"id":3,"username":"liulaoshi","age":16}, 12 {"id":4,"username":"liulaoshi","age":15}, 13 ] 14 return jsonify(data) 15 16 #使用url_for可以實現視圖方法之間的內部跳轉 17 # url_for("視圖方法名") 18 from flask import Flask, request, jsonify, redirect, url_for 19 @app.route("/login") 20 def login(): 21 return redirect( url_for("index") )
重定向到帶有參數的視圖函數
在 url_for 函數中傳入參數
1 # 路由傳遞參數 2 @app.route('/user/<user_id>') 3 def user_info(user_id): 4 return 'hello %s' % user_id 5 6 # 重定向 7 @app.route('/demo4') 8 def demo4(): 9 # 使用 url_for 生成指定視圖函數所對應的 url 10 return redirect(url_for('user_info', user_id=100))
自定義狀態碼
在 Flask 中,可以很方便的返回自定義狀態碼,以實現不符合 http 協議的狀態碼,例如:status code: 666
1 @app.route('/demo4') 2 def demo4(): 3 return '狀態碼為 666', 400
三、會話控制
所謂的會話,就是用戶和瀏覽器中網站之間一次交互過程.
會話的開始是在用戶打開瀏覽器以后第一次訪問網站.
會話的結束時在用戶關閉瀏覽器以后.
因為 http 是一種無狀態協議,瀏覽器請求服務器是無狀態的。
無狀態:指一次用戶請求時,瀏覽器、服務器無法知道之前這個用戶做過什么,每次請求都是一次新的請求。
無狀態原因:瀏覽器與服務器是使用 socket 套接字進行通信的,服務器將請求結果返回給瀏覽器之后,會關閉當前的 socket 連接,而且服務器也會在處理頁面完畢之后銷毀頁面對象。
有時需要保持下來用戶瀏覽的狀態,比如用戶是否登錄過,瀏覽過哪些商品等
實現狀態保持主要有兩種方式:
- 在客戶端存儲信息使用
Cookie,本地存儲,token[jwt,oauth]
- 在服務器端存儲信息使用
Session
,redis
四、cookie
Cookie是由服務器端生成,發送給客戶端瀏覽器,瀏覽器會將Cookie的key/value保存,下次請求同一網站時就發送該Cookie給服務器(前提是瀏覽器設置為啟用cookie)。Cookie的key/value可以由服務器端自己定義。
使用場景: 登錄狀態, 瀏覽歷史, 網站足跡
Cookie是存儲在瀏覽器中的一段純文本信息,建議不要存儲敏感信息如密碼,因為電腦上的瀏覽器可能被其它人使用
Cookie基於域名安全,不同域名的Cookie是不能互相訪問的
如訪問luffy.com時向瀏覽器中寫了Cookie信息,使用同一瀏覽器訪問baidu.com時,無法訪問到luffy.com寫的Cookie信息
瀏覽器的同源策略針對cookie也有限制作用.
當瀏覽器請求某網站時,會將本網站下所有Cookie信息提交給服務器,所以在request中可以讀取Cookie信息
設置cookie
設置cookie需要通過flask的Response響應對象來進行設置,由flask內部提供了一個make_response函數給我們可以快速創建響應對象
1 from flask imoprt Flask,make_response 2 @app.route('/set_cookie') 3 def set_cookie(): 4 resp = make_response('this is to set cookie') 5 resp.set_cookie('username', 'xiaoming', max_age=3600) 6 # max_age 為cookie有效期,單位為秒 7 return resp
獲取cookie
1 from flask import Flask,request 2 @app.route('/get_cookie') 3 def resp_cookie(): 4 resp = request.cookies.get('username') 5 return resp
五、session
對於敏感、重要的信息,建議要存儲在服務器端,不能存儲在瀏覽器中,如用戶名、余額、等級、驗證碼等信息
在服務器端進行狀態保持的方案就是Session
注意: Session依賴於Cookie,而且flask中使用session,需要配置SECRET_KEY選項,否則報錯.
設置session
1 from flask import session 2 @app.route('/set_session') 3 def set_session(): 4 session['username'] = 'xiaoming' 5 return 'ok!'
獲取session
1 @app.route('/get_session') 2 def get_session(): 3 return session.get('username')