Flask快速上手

A༒࿈發表於2020-11-18

img

一.簡介

Flask誕生於2010年,是Armin ronacher(人名)用 Python 語言基於 Werkzeug 工具箱編寫的輕量級Web開發框架。

官網: https://flask.palletsprojects.com/en/1.1.x/

官方文件: http://docs.jinkan.org/docs/flask/

Flask常用第三方擴充套件包:

  • Flask-SQLalchemy:運算元據庫,ORM;
  • Flask-script:終端指令碼工具,腳手架;
  • Flask-migrate:管理遷移資料庫;
  • Flask-Session:Session儲存方式指定;
  • Flask-WTF:表單;
  • Flask-Mail:郵件;
  • Flask-Bable:提供國際化和本地化支援,翻譯;
  • Flask-Login:認證使用者狀態;
  • Flask-OpenID:認證, OAuth;
  • Flask-RESTful:開發REST API的工具;
  • Flask JSON-RPC: 開發rpc遠端服務[過程]呼叫
  • Flask-Bootstrap:整合前端Twitter Bootstrap框架
  • Flask-Moment:本地化日期和時間
  • Flask-Admin:簡單而可擴充套件的管理介面的框架

二. 安裝

mkvirtualenv flask -p python3

在這裡插入圖片描述

pip install flask==0.12.5

在這裡插入圖片描述

三. 建立flask專案

flask需要我們手動建立專案

在這裡插入圖片描述

建立一個flask框架的主程式。名字可以是app.py/run.py/main.py/index.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World'

if __name__ == '__main__':
    app.run()

程式碼分析:

# 匯入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(import_name=__name__)


# 編寫路由檢視
# flask的路由是通過給檢視新增裝飾器的方式進行編寫的。當然也可以分離到另一個檔案中。
# flask的檢視函式,flask中預設允許通過return返回html格式資料給客戶端。
@app.route('/')
def index():
    return "<h1>hello world</h1>"

# 載入專案配置
class Config(object):
    # 開啟除錯模式
    DEBUG = True

# flask中支援多種配置方式,通過app.config來進行載入,我們會這裡常用的是配置類
app.config.from_object( Config )


# 指定伺服器IP和埠
if __name__ == '__main__':
    # 執行flask
    app.run(host="0.0.0.0", port=5000)

四. 路由的基本定義

路由和檢視的名稱必須全域性唯一,不能出現重複,否則報錯。

# 指定訪問路徑為 index
@app.route('/index')
def demo1():
    return 'index'

url中可以傳遞路由引數, 2種方式

路由引數就是url路徑的一部分。

任意路由引數接收

# 路由傳遞引數[沒有限定型別]
@app.route('/user/<user_id>')
def user_info(user_id):
    return 'hello %s' % user_id

限定路由引數接收

限定路由引數的型別,flask系統自帶轉換器編寫在werkzeug.routing.py檔案中。底部可以看到以下字典:

DEFAULT_CONVERTERS = {
    "default": UnicodeConverter,
    "string": UnicodeConverter,
    "any": AnyConverter,
    "path": PathConverter,
    "int": IntegerConverter,
    "float": FloatConverter,
    "uuid": UUIDConverter,
}

系統自帶的轉換器具體使用方式在每種轉換器的註釋程式碼中有寫,請留意每種轉換器初始化的引數。

轉換器名稱描述
string預設型別,接受不帶斜槓的任何文字
int接受正整數
float接受正浮點值
path接收string但也接受斜線
uuid接受UUID(通用唯一識別碼)字串 xxxx-xxxx-xxxxx-xxxxx

程式碼:

# flask提供了路由轉換器可以讓我們對路由引數進行限定
# 路由傳遞引數[限定資料型別]
@app.route('/user/<int:user_id>')
def user_info(user_id):
    return 'hello %d' % user_id

自定義路由引數轉換器

也叫正則匹配路由引數.

在 web 開發中,可能會出現限制使用者訪問規則的場景,那麼這個時候就需要用到正則匹配,根據自己的規則去限定請求引數再進行訪問

具體實現步驟為:

  • 匯入轉換器基類:在 Flask 中,所有的路由的匹配規則都是使用轉換器物件進行記錄
  • 自定義轉換器:自定義類繼承於轉換器基類
  • 新增轉換器到預設的轉換器字典中
  • 使用自定義轉換器實現自定義匹配規則

程式碼實現

  • 匯入轉換器基類
from werkzeug.routing import BaseConverter
  • 自定義轉換器
# 自定義正則轉換器
from werkzeug.routing import BaseConverter
class RegexConverter(BaseConverter):
    def __init__(self,map,*args):
        super().__init__(map)
        # 正則引數
        self.regex = args[0]
  • 新增轉換器到預設的轉換器字典中,並指定轉換器使用時名字為: re
# 將自定義轉換器新增到轉換器字典中,並指定轉換器使用時名字為: 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不符合規則,會提示找不到頁面

from flask import Flask,request
# 初始化
app = Flask(import_name=__name__)

# 編寫路由檢視
@app.route(rule='/')
def index():
    return "<h1>hello world!</h1>"

# 關於路由引數的限制,flask內建的型別不夠具體,在開發中,我們經常接受引數,需要更加精確的限制
# 這時候,可以使用正則匹配路由引數
# 正則匹配路由引數,其實就是擴充套件flask內建的路由限定型別,需要完成4個步驟
# 1. 引入flask的路由轉換器
from werkzeug.routing import BaseConverter
# 2. 建立自定義路由轉換器
class MobileConverter(BaseConverter):
    """手機號碼型別限制"""
    def __init__(self,map,*args):
        super().__init__(map)
        self.regex = "1[3-9]\d{9}"
# 3. 把自定義轉換器新增到flask預設的轉換器字典中,也就是和原來的int,float等放在一塊
app.url_map.converters['mob'] = MobileConverter

# 4. 類似原來的路由引數限制一樣,呼叫自定義轉換器名稱即可
@app.route(rule='/user/<mob:mobile>')
def user(mobile):
    return mobile

# 1. 引入flask的路由轉換器
from werkzeug.routing import BaseConverter
# 2. 建立自定義路由轉換器
class RegexConverter(BaseConverter):
    """根據正則進行引數限制"""
    def __init__(self,map,*args):
        super().__init__(map)
        self.regex = args[0]
# 3. 把自定義轉換器新增到flask預設的轉換器字典中,也就是和原來的int,float等放在一塊
app.url_map.converters['re'] = RegexConverter

# 4. 類似原來的路由引數限制一樣,呼叫自定義轉換器名稱即可
@app.route(rule='/user/<re("\w+@\w+\.\w+"):email>')
def user2(email):
    print(app.url_map) # 獲取所有的路由列表
    return email

# 宣告和載入配置
class Config():
    DEBUG = True
app.config.from_object(Config)

if __name__ == '__main__':
    # 執行flask
    app.run(host="0.0.0.0")

路由限定請求方式

from flask import Flask,request
# 限制客戶端的http請求方法,注意這裡與django不一樣,flask並沒有預設沒有內建csrf攻擊防範
@app.route(rule="/user", methods=["post","put","get","delete","patch"])
def user():
    
    # 例如:位址列中通過  http://127.0.0.1:5000/user?user=1 返回本檢視
    
    print(request.method) # 獲取本次客戶端的http請求方法         GET
    print(request.query_string)  # 獲取本次客戶端的查詢字串    b'user=1'
    print(request.path)  # 獲取本次客戶端請求的路由路徑部分[去掉域名埠]    /user
    print(request.url) # 獲取本次客戶端請求的http url地址        http://127.0.0.1:5000/user?user=1
    # 直接從請求中取到請求方式並返回
    return request.method

http的請求與響應

請求

文件: http://docs.jinkan.org/docs/flask/api.html#flask.request

  • request:flask中代表當前請求的 request 物件
  • 作用:在檢視函式中取出本次請求資料
  • 匯入from flask import request
  • 程式碼位置:from flask.app import Request

常用的屬性如下:

屬性說明型別
data記錄請求體的資料,並轉換為字串
只要是通過其他屬性無法識別轉換的請求體資料
最終都是保留到data屬性中
bytes型別
form記錄請求中的html表單資料MultiDict
args記錄請求中的查詢字串,也可以是query_stringMultiDict
cookies記錄請求中的cookie資訊Dict
headers記錄請求中的請求頭EnvironHeaders
method記錄請求使用的HTTP方法GET/POST
url記錄請求的URL地址string
files記錄請求上傳的檔案列表*
json記錄ajax請求的json資料json

獲取請求中各項資料

from flask import Flask,request

# 初始化
app = Flask(import_name=__name__)
# 編寫路由檢視
@app.route(rule='/')
def index():
    return "<h1>hello world!</h1>"

"""== 獲取查詢字串 =="""
@app.route(rule="/args",methods=["post","get"])
def args():
    print(request.args) # 獲取查詢字串
    """
    請求地址:
        http://127.0.0.1:5000/args?name=xiaoming&password=123&lve=swimming&lve=shopping
    列印效果:
        ImmutableMultiDict([('name', 'xiaoming'), ('password', '123')])
        ImmutableMultiDict是一個由flask封裝的字典類,在字典的基礎上,提供了一些其他的方法而已。
        格式:
            ImmutableMultiDict([('鍵', '值'), ('鍵', '值')])
        字典本身不支援同名鍵的,ImmutableMultiDict類解決了鍵同名問題
        操作ImmutableMultiDict,完全可以操作字典操作,同時還提供了get,getlist方法,獲取指定鍵的1個值或多個值
        還提供了2個方法,一個是to_dict,另一個是to_list
    """
    print(request.args["name"]) # xiaoming
    print(request.args.get("name")) # xiaoming
    print(request.args.getlist("lve")) # ['swimming', 'shopping']

    # 把ImmutableMultiDict轉換成普通字典
    print(request.args.to_dict(flat=False)) # {'name': ['xiaoming'], 'password': ['123'], 'lve': ['swimming', 'shopping']}
    print(request.args.to_dict(flat=True)) # {'name': 'xiaoming', 'password': '123', 'lve': 'swimming'}

    return "ok"

"""== 獲取請求體資料 =="""
@app.route(rule="/data",methods=["post","put","patch"])
def data():
    """接受客戶端傳送過來的請求體資料,是request.json,request.form,request.files等無法接受的資料,全部會保留到這裡"""
    print(request.data) #

    # 接受表單提交的資料
    print(request.form) # ImmutableMultiDict([('username', 'root'), ('password', '123456')])

    # 接受ajax或其他客戶端提交過來的json資料
    print(request.json) # {'username': 'root', 'password': '123456'}

    # 接受上傳檔案
    avatar = request.files["avatar"] # ImmutableMultiDict([('avatar', <FileStorage: '123.jpg' ('image/jpeg')>)])
    print(avatar) # <FileStorage: '123.jpg' ('image/jpeg')>


    # 獲取請求頭資訊
    print( request.headers ) # 獲取全部的而請求頭資訊
    print( request.headers.get("Host") )
    # 獲取自定義請求頭
    print( request.headers.get("company") ) # oldboy
    print( request.headers["company"] )     # oldboy
    
    # 本次請求的url地址
    print( request.url) # http://127.0.0.1:5000/data
    print( request.path ) # /data
    
    return "ok"

# 宣告和載入配置
class Config():
    DEBUG = True
app.config.from_object(Config)

if __name__ == '__main__':
    # 執行flask
    app.run(host="0.0.0.0")

響應

flask預設支援2種響應方式:

資料響應: 預設響應html文字,也可以返回 JSON格式,或其他格式

頁面響應: 重定向

​ url_for 檢視之間的跳轉

響應的時候,flask也支援自定義http響應狀態碼

響應html文字

from flask import make_response

@app.route("/")
def index():
    # [預設支援]響應html文字
    return "<img src='http://flask.pocoo.org/static/logo.png'>"
	return make_response("<h1>hello user</h1>") # 等同於上面的一段

返回JSON資料

在 Flask 中可以直接使用 jsonify 生成一個 JSON 的響應

from flask import Flask, request, jsonify
# jsonify 就是json裡面的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 redirect
# 頁面跳轉響應
@app.route("/user")
def user():
    # 頁面跳轉 redirect函式就是response物件的頁面跳轉的封裝
    # Location: http://www.baidu.com
    return redirect("http://www.baidu.com")
重定向到自己寫的檢視函式

可以直接填寫自己 url 路徑

也可以使用 url_for 生成指定檢視函式所對應的 url

from flask import url_for

# 內容響應
@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("檢視方法名")
@app.route("/login")
def login():
    return redirect( url_for("index") )
重定向到帶有引數的檢視函式

在 url_for 函式中傳入引數

# 路由傳遞引數
@app.route('/user/<user_id>')
def user_info(user_id):
    return 'hello %d' % user_id

# 重定向
@app.route('/demo4')
def demo4():
    # 使用 url_for 生成指定檢視函式所對應的 url
    return redirect( url_for(endpoint="user",user_id=100) )

自定義狀態碼和響應頭

在 Flask 中,可以很方便的返回自定義狀態碼,以實現不符合 http 協議的狀態碼,例如:status code: 666

@app.route('/demo4')
def demo4():
    return '狀態碼為 666', 400
  
"""還可以使用make_response建立Response物件,然後通過response物件返回資料"""
from flask import make_response
@app.route("/rep")
def index7():
    response = make_response("ok")
    print(response)
    response.headers["Company"] = "oldboy" # 自定義響應頭
    response.status_code = 201 # 自定義響應狀態碼
    return response

相關文章