轉載請在文章開頭附上原文連接地址:http://www.javashuo.com/article/p-gczicoym-bn.html
Flask誕生於2010年,是Armin ronacher(人名)用 Python 語言基於 Werkzeug 工具箱編寫的輕量級Web開發框架。
Flask 自己至關於一個內核,其餘幾乎全部的功能都要用到擴展(郵件擴展Flask-Mail,用戶認證Flask-Login,數據庫Flask-SQLAlchemy),都須要用第三方的擴展來實現。好比能夠用 Flask 擴展加入ORM、窗體驗證工具,文件上傳、身份驗證等。Flask 沒有默認使用的數據庫,你能夠選擇 MySQL,也能夠用 NoSQL。html
其 WSGI 工具箱採用 Werkzeug(路由模塊),模板引擎則使用 Jinja2。這兩個也是 Flask 框架的核心。前端
官網: http://flask.pocoo.org/python
官方文檔: http://docs.jinkan.org/docs/flask/web
Flask經常使用擴展包:redis
能夠經過 http://flask.pocoo.org/extensions/ 查看更多flask官方推薦的擴展數據庫
mkvirtualenv flask_demo -p python3
pip install flask==0.12.4
與django不一樣,flask不會提供任何的自動操做,因此須要手動建立項目目錄,須要手動建立啓動項目的管理文件django
例如,建立項目目錄 flaskdemo,在目錄中建立manage.py.在pycharm中打開項目並指定上面建立的虛擬環境json
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'Hello World' if __name__ == '__main__': app.run()
代碼分析:flask
# 導入Flask類 from flask import Flask """ import_name Flask程序所在的包(模塊),傳 __name__ 就能夠 其能夠決定 Flask 在訪問靜態文件時查找的路徑 static_path 靜態文件訪問路徑(不推薦使用,使用 static_url_path 代替) static_url_path 靜態文件訪問路徑,能夠不傳,默認爲:/ + static_folder static_folder 靜態文件存儲的文件夾,能夠不傳,默認爲 static template_folder 模板文件存儲的文件夾,能夠不傳,默認爲 templates """ app = Flask(__name__)
# 加載項目配置 # 配置類 class Config(object): DEBUG = True SECRET_KEY = "abcccddgadsag" app.config.from_object( Config ) # 指定服務器IP和端口 app.run(host="0.0.0.0", port=5000, debug = True)
# 指定訪問路徑爲 demo1 @app.route('/demo1') def demo1(): return 'demo1'
# 路由傳遞參數[沒有限定類型] @app.route('/user/<user_id>') def user_info(user_id): return 'hello %s' % user_id # 路由傳遞參數[限定數據類型] @app.route('/user/<int:user_id>') def user_info(user_id): return 'hello %d' % user_id
from flask import Flask, request @app.route('/demo2', methods=['GET', 'POST']) def demo2(): # 直接從請求中取到請求方式並返回 return request.method
在 web 開發中,可能會出現限制用戶訪問規則的場景,那麼這個時候就須要用到正則匹配,根據本身的規則去限定請求參數再進行訪問api
具體實現步驟爲:
from werkzeug.routing import BaseConverter
# 自定義正則轉換器 from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): def __init__(self,url_map,*args): super(RegexConverter, self).__init__(url_map) # 正則參數 self.regex = args[0]
# 將自定義轉換器添加到轉換器字典中,並指定轉換器使用時名字爲: re app.url_map.converters['re'] = RegexConverter
# 正則匹配路由 @app.route("/login/<re('1\d{10}'):mobile>") def login(mobile): return mobile
運行測試:http://127.0.0.1:5000/login/1311111111 ,若是訪問的url不符合規則,會提示找不到頁面
DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'path': PathConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter, }
系統自帶的轉換器具體使用方式在每種轉換器的註釋代碼中有寫,請留意每種轉換器初始化的參數。
from flask import Flask # 新增一個配置文件,在配置文件中設置配置信息 from config import Config from flask import request # from collections import OrderedDict # 有序字典 app = Flask(__name__) # 調用app.config加載配置 app.config.from_object(Config) from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): def __init__(self,url_map,*args): super(RegexConverter, self).__init__(url_map) # 正則參數 self.regex = args[0] # converter["路由轉換器名稱"] = 實現路由轉換功能的自定義類 app.url_map.converters['re'] = RegexConverter # 綁定路由 @app.route("/") def index(): return "hello flask" # 默認狀況下,路由使用的就是關鍵字參數,也叫"命名路由" # router(路由地址, http請求方式 ) @app.route("/list/<int:page>/<string:content>",methods=["GET","POST"]) def mylist(content,page): return "第%s頁<br>內容:%s" % (page,content) # 正則匹配路由 @app.route("/login/<re('1\d{10}'):mobile>") def login(mobile): return mobile
文檔: http://docs.jinkan.org/docs/flask/api.html#flask.request
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
...... """獲取客戶端的請求""" @app.route("/request") def req1(): """獲取查詢字符串""" query_string = request.args print(query_string) # 瀏覽器輸入 http://127.0.0.1:5000/request?a=1&b=2 """打印效果: ImmutableMultiDict([('a', '1'), ('b', '2')])""" # 獲取一個參數的一個值 http://127.0.0.1:5000/request?username=abcd username = request.args.get("username") # print(username) """打印效果: abcd """ # 獲取一個參數的多個值 # http://127.0.0.1:5000/request?username=xiaoming&love=吹牛&love=睡覺 love = request.args.getlist("love") # print(love) """打印效果: ['吹牛', '睡覺']""" # 把傳遞過來的數據抓換成原生的字典 data = request.args.to_dict() # print(data) """打印效果:{'username': 'xiaoming', 'love': '吹牛'} """ return "ok" @app.route("/request2",methods=["POST"]) def req2(): """獲取post數據和請求頭""" # 必須傳 json 格式的數據 # print( request.data ) # """打印結果: # b'{\n\t"username":"xiaoming",\n\t"age":18,\n\t"sex":1\n}' # """ # 方式一 # import json # from flask import json # data = json.loads(request.data) # print(data) # """打印結果: # {'username': 'xiaoming', 'age': 18, 'sex': 1} #方式二 print(request.json) # """打印結果: # {'username': 'xiaoming', 'age': 18, 'sex': 1} # """ # # """獲取請求行數據""" # print( request.headers ) # print( request.headers.to_list() ) """獲取上傳文件""" print( request.files ) print( request.files.get("avatar") ) """打印效果: ImmutableMultiDict([('avatar', <FileStorage: 'avatar.png' ('image/png')>)]) <FileStorage: 'avatar.png' ('image/png')> """ return "ok" if __name__ == '__main__': app.run()
flask默認支持2種響應方式:
響應的時候,flask也支持自定義http響應狀態碼
@app.route("/") def index(): # [默認支持]響應html文本 return "<img src='http://flask.pocoo.org/static/logo.png'>"
在 Flask 中能夠直接使用 jsonify 生成一個 JSON 的響應
from flask import Flask, request, jsonify @app.route("/") def index(): # 也能夠響應json格式代碼 data = [ {"id":1,"username":"liulaoshi","age":18}, {"id":2,"username":"liulaoshi","age":17}, {"id":3,"username":"liulaoshi","age":16}, {"id":4,"username":"liulaoshi","age":15}, ] return jsonify(data)
flask中返回json 數據,都是flask的jsonify方法返回就能夠了.
# 頁面跳轉響應 from flask import Flask, request, jsonify, redirect @app.route("/user") def user(): # 頁面跳轉 redirect函數就是response對象的頁面跳轉的封裝 # Location: http://www.baidu.com return redirect("http://www.baidu.com")
能夠直接填寫本身 url 路徑
也可使用 url_for 生成指定視圖函數所對應的 url
# 內容響應 @app.route("/") def index(): # [默認支持]響應html文本 # return "<img src='http://flask.pocoo.org/static/logo.png'>" # 也能夠響應json格式代碼 data = [ {"id":1,"username":"liulaoshi","age":18}, {"id":2,"username":"liulaoshi","age":17}, {"id":3,"username":"liulaoshi","age":16}, {"id":4,"username":"liulaoshi","age":15}, ] return jsonify(data) #使用url_for能夠實現視圖方法之間的內部跳轉 # url_for("視圖方法名") from flask import Flask, request, jsonify, redirect, url_for @app.route("/login") def login(): return redirect( url_for("index") )
在 url_for 函數中傳入參數
# 路由傳遞參數 @app.route('/user/<user_id>') def user_info(user_id): return 'hello %s' % user_id # 重定向 @app.route('/demo4') def demo4(): # 使用 url_for 生成指定視圖函數所對應的 url return redirect(url_for('user_info', user_id=100))
在 Flask 中,能夠很方便的返回自定義狀態碼,以實現不符合 http 協議的狀態碼,例如:status code: 666
@app.route('/demo4') def demo4(): return '狀態碼爲 666', 400
所謂的會話,就是用戶和瀏覽器中網站之間一次交互過程.
會話的開始是在用戶打開瀏覽器之後第一次訪問網站.
會話的結束時在用戶關閉瀏覽器之後.
由於 http 是一種無狀態協議,瀏覽器請求服務器是無狀態的。
無狀態:指一次用戶請求時,瀏覽器、服務器沒法知道以前這個用戶作過什麼,每次請求都是一次新的請求。
無狀態緣由:瀏覽器與服務器是使用 socket 套接字進行通訊的,服務器將請求結果返回給瀏覽器以後,會關閉當前的 socket 鏈接,並且服務器也會在處理頁面完畢以後銷燬頁面對象。
有時須要保持下來用戶瀏覽的狀態,好比用戶是否登陸過,瀏覽過哪些商品等
實現狀態保持主要有兩種方式:
Cookie,本地存儲,token[jwt,oauth]
Session
,redisCookie是由服務器端生成,發送給客戶端瀏覽器,瀏覽器會將Cookie的key/value保存,下次請求同一網站時就發送該Cookie給服務器(前提是瀏覽器設置爲啓用cookie)。Cookie的key/value能夠由服務器端本身定義。
使用場景: 登陸狀態, 瀏覽歷史, 網站足跡
Cookie是存儲在瀏覽器中的一段純文本信息,建議不要存儲敏感信息如密碼,由於電腦上的瀏覽器可能被其它人使用
Cookie基於域名安全,不一樣域名的Cookie是不能互相訪問的
如訪問luffy.com時向瀏覽器中寫了Cookie信息,使用同一瀏覽器訪問baidu.com時,沒法訪問到luffy.com寫的Cookie信息
瀏覽器的同源策略針對cookie也有限制做用.
當瀏覽器請求某網站時,會將本網站下全部Cookie信息提交給服務器,因此在request中能夠讀取Cookie信息
設置cookie須要經過flask的Response響應對象來進行設置,由flask內部提供了一個make_response函數給咱們能夠快速建立響應對象
from flask imoprt Flask,make_response @app.route('/set_cookie') def set_cookie(): resp = make_response('this is to set cookie') resp.set_cookie('username', 'xiaoming', max_age=3600) # max_age 爲cookie有效期,單位爲秒 return resp
from flask import Flask,request @app.route('/get_cookie') def resp_cookie(): resp = request.cookies.get('username') return resp
對於敏感、重要的信息,建議要存儲在服務器端,不能存儲在瀏覽器中,如用戶名、餘額、等級、驗證碼等信息
在服務器端進行狀態保持的方案就是Session
注意: Session依賴於Cookie,並且flask中使用session,須要配置SECRET_KEY選項,不然報錯.
from flask import session @app.route('/set_session') def set_session(): session['username'] = 'xiaoming' return 'ok!'
@app.route('/get_session') def get_session(): return session.get('username')