8 最全的零基礎Flask教程

来源:https://www.cnblogs.com/likeLfcf/archive/2023/08/06/17610236.html
-Advertisement-
Play Games

# 最全的零基礎Flask教程 ## 1 Flask介紹 ### 1.1 為什麼要使用Flask Django和Flask是Python使用最多的兩個框架 ![image-20230802071519906](https://img2023.cnblogs.com/blog/2602103/2023 ...


最全的零基礎Flask教程

1 Flask介紹

1.1 為什麼要使用Flask

Django和Flask是Python使用最多的兩個框架

image-20230802071519906

1.2 Flask是什麼

image-20230802071649730

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

Flask 本身相當於一個內核,其他幾乎所有的功能都要用到擴展(郵件擴展Flask-Mail,用戶認證Flask-Login,資料庫Flask-SQLAlchemy),都需要用第三方的擴展來實現。比如可以用 Flask 擴展加入ORM、窗體驗證工具,文件上傳、身份驗證等。Flask 沒有預設使用的資料庫,你可以選擇 MySQL,也可以用 NoSQL。

其 WSGI 工具箱採用 Werkzeug(路由模塊),模板引擎則使用 Jinja2。這兩個也是 Flask 框架的核心。

1.3 Flask與Django框架對比

1.3.1 框架輕重

重量級的框架:為方便業務程式的開發,提供了豐富的工具、組件,如Django

輕量級的框架:只提供Web框架的核心功能,自由、靈活、高度定製,如Flask、Tornado

1.3.2 與Django對比

django提供了:

  • django-admin快速創建項目工程目錄
  • manage.py 管理項目工程
  • orm模型(資料庫抽象層)
  • admin後臺管理站點
  • 緩存機制
  • 文件存儲系統
  • 用戶認證系統
  • 而這些,flask都沒有,都需要擴展包來提供

1.4 Flask常用擴展包

  • Flask-SQLalchemy:操作資料庫;
  • Flask-script:插入腳本;
  • Flask-migrate:管理遷移資料庫;
  • Flask-Session:Session存儲方式指定;
  • Flask-WTF:表單;
  • Flask-Mail:郵件;
  • Flask-Bable:提供國際化和本地化支持,翻譯;
  • Flask-Login:認證用戶狀態;
  • Flask-OpenID:認證;
  • Flask-RESTful:開發REST API的工具;
  • Flask-Bootstrap:集成前端Twitter Bootstrap框架;
  • Flask-Moment:本地化日期和時間;
  • Flask-Admin:簡單而可擴展的管理介面的框架

1.5 Flask文檔

2 工程搭建

2.1 環境安裝

2.1.1 Anaconda常用虛擬環境命令

# 虛擬環境
conda create -n 虛擬環境名稱 python=python版本號  # 創建虛擬環境
conda remove -n 虛擬環境名稱 --all  # 刪除虛擬環境
conda activate 虛擬環境名稱  # 激活虛擬環境
conda env list 或 conda info -e # 查看全部虛擬環境
deactivate 虛擬環境名稱  # 退出虛擬環境

2.1.2. 創建虛擬環境

Flask 再2.3.0版本上已經放棄對Python3.7的支持,當前支持的Python把版本區間為3.7~3.12,因此這裡將Python的版本定為3.8

conda create -n FlaskWeb python=3.8

image-20230802073815252

2.1.3. 安裝Flask

使用flask 2.3.0版本

pip install flask==2.3.0

image-20230802074039874

2.2 HelloWorld程式

2.2.1 Flask編寫

image-20230802074432847

2.2.2 Flaks手動運行

1 Pycharm運行

image-20230802074712971

2 命令行運行

image-20230802074614735

3 訪問測試

image-20230802074735503

2.3 參數說明

2.3.1 Flask對象初始化參數

Flask 程式實例在創建的時候,需要預設傳入當前 Flask 程式所指定的包(模塊),下麵說明一些常用的Flask參數:

1 import_name

  • Flask程式所在的包(模塊),傳 __name__ 就可以
  • 其可以決定 Flask 在訪問靜態文件時查找的路徑

image-20230802075714586

2 static_url_path

  • 靜態文件訪問路徑,可以不傳,預設為:/ + static_folder

image-20230802080042435

3 static_folder

  • 靜態文件存儲的文件夾,可以不傳,預設為 static

image-20230802075746656

template_folder

  • 模板文件存儲的文件夾,可以不傳,預設為 templates

image-20230802080139543

預設參數情況下,訪問靜態資源

app = Flask(__name__)

image-20230802080505145

image-20230802080600221

修改參數的情況下,訪問靜態資源

# 定義靜態資源的訪問路徑為url_path_param,靜態資源文件夾名稱為folder_param
app = Flask(__name__, static_url_path='/url_path_param', static_folder='folder_param')

image-20230802080943788

image-20230802081022426

image-20230802081108141

2.3.2 應用程式配置參數

Flask將配置信息保存到了app.config屬性中,該屬性可以按照字典類型進行操作。

1 讀取配置參數

  • app.config.get(name)
  • app.config[name]

2 設置

Flask配置參數,主要使用以下三種方式:

從配置對象中載入

app.config.from_object(配置對象)

# 定義預設配置類
class DefultConfig(object):
    """
    預設配置
    """
    SECRET_KEY = "lalalalalala"
# 定義開發環境下的配置類,繼承自預設配置類
class DevDefultConfig(DefultConfig):
    DEBUG=True

app = Flask(__name__)
# 從配置對象中添加配置
app.config.from_object(DefultConfig)

應用場景:

image-20230802082204782

從配置文件中載入

app.config.from_pyfile(配置文件)

新建一個配置文件setting.py

SECRET_KEY = 'TPmi4aLWRbyVq8zu9v82dWYW1'

image-20230802082450925

在Flask程式文件中讀取該配置文件

# 從配置文件中添加配置
app.config.from_pyfile("setting.py")
@app.route("/")
def index():
    return app.config["SECRET_KEY"]

image-20230802082607531

訪問測試

image-20230802082629470

3 從環境變數中載入配置信息

環境變數(environment variables)一般是指在操作系統中用來指定操作系統運行環境的一些參數,如:臨時文件夾位置和系統文件夾位置等。

環境變數是在操作系統中一個具有特定名字的對象,它包含了一個或者多個應用程式所將使用到的信息。

通俗的理解,環境變數就是我們設置在操作系統中,由操作系統代為保存的變數值

Flask使用環境變數載入配置的本質是通過環境變數值找到配置文件,再讀取配置文件的信息,其使用方式為:


代碼查詢環境變數的方式:

# 環境變數中存儲的是配置文件的絕對地址
app.config.from_envvar('環境變數名')

兩種定義環境變數的方式

Windows環境下定義臨時環境變數

set 臨時環境變數名稱 = 變數的值

image-20230802084536274

Pycharm下定義環境變數的方式

image-20230802084559640

image-20230802084700897

image-20230802084736282


示例:

再運行程式,即可。

app = Flask(__name__)

app.config.from_envvar('PROJECT_SETTING', silent=True)

@app.route("/")
def index():
    print(app.config['SECRET_KEY'])
    return "hello world"

關於silent參數的說明:

表示系統環境變數中沒有設置相應值時是否拋出異常

  • False 表示不安靜的處理,沒有值時報錯通知,預設為False
  • True 表示安靜的處理,即時沒有值也讓Flask正常的運行下去

image-20230802085515237

image-20230802085542705

訪問測試

image-20230802085611448

項目中的常用方式

使用工廠模式創建Flask app,並結合使用配置對象與環境變數載入配置

  • 使用配置對象載入預設配置
  • 使用環境變數載入不想出現在代碼中的敏感配置信息
def create_flask_app(config):
    """
    創建Flask應用
    :param config: 配置對象
    :return: Flask應用
    """
    app = Flask(__name__)
    app.config.from_object(config)

    # 從環境變數指向的配置文件中讀取的配置信息會覆蓋掉從配置對象中載入的同名參數
    app.config.from_envvar("PROJECT_SETTING", silent=True)
    return app

image-20230802090050970

方便了程式的使用,是一種常用的方式

2.3.3 app.run 參數

可以指定運行的主機IP地址,埠,是否開啟調試模式

app.run(host="0.0.0.0", port=5000, debug = True)

image-20230802085732904

image-20230802085849957

關於DEBUG調試模式

  1. 程式代碼修改後可以自動重啟伺服器
  2. 在伺服器出現相關錯誤的時候可以直接將錯誤信息返回到前端進行展示

2.4 開發伺服器啟動方式

在1.0版本之後,Flask調整了開發伺服器的啟動方式,由代碼編寫app.run()語句調整為命令flask run啟動。

from flask import Flask

app = Flask(__name__)

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

# 程式中不用再寫app.run()

image-20230802095457149

啟動

# 指定FLASK_APP環境變數(Windows CMD環境),demo01是文件名
set FLASK_APP=demo01
# 執行
flask run

image-20230802095648261

image-20230802095706081

說明

  • 環境變數 FLASK_APP 指明flask的啟動實例

  • flask run -h 0.0.0.0 -p 8000 綁定地址 埠

  • flask run --help獲取幫助

  • 生產模式與開發模式的控制

    通過FLASK_ENV環境變數指明

    • set FLASK_ENV=production 運行在生產模式,未指明則預設為此方式
    • set FLASK_ENV=development運行在開發模式

擴展:指定參數運行

flask run --host 127.0.0.1 --port 6666

image-20230802095753834

3 路由與藍圖

3.1 路由

image-20230802092422505

3.1.1 查詢路由信息

需要提前設置好FLASK_APP環境變數的值,並且cmd處於管理員模式

命令行方式

flask routes

image-20230802092909185

在程式中獲取

在應用中的url_map屬性中保存著整個Flask應用的路由映射信息,可以通過讀取這個屬性獲取路由信息

print(app.url_map)

image-20230802093155610

image-20230802093135681

在程式中遍歷路由信息

for rule in app.url_map.iter_rules():
    print('name={} path={}'.format(rule.endpoint, rule.rule))

image-20230802093235245

image-20230802093337154

測試

實現通過訪問/routes地址,以json的方式返回應用內的所有路由信息

import json
from flask import Flask

app = Flask(__name__)

@app.route("/flaskRoutes")
def getRoutes():
    context = {}
    for rule in app.url_map.iter_rules():
        context[rule.endpoint] = rule.rule
    return json.dumps(context)

image-20230802094105382

3.1.2 指定請求方式

在 Flask 中,定義路由其預設的請求方式為:

  • GET
  • OPTIONS(自帶)
  • HEAD(自帶)

利用methods參數可以自己指定一個介面的多個請求方式,@app.get()指定的是get請求方式,@app.post()指定的是post請求方式,以此類推

image-20230802095014289

image-20230802094837860

image-20230802094849964

這裡只測試了兩個,其餘的基本相似(這裡採用的是Apifox進行測試)

3.2 藍圖

如果一個大的項目有多個模塊,在Flask中可以採用藍圖進行開發,對藍圖的理解可以對比Django中的子應用。在Flask中,使用藍圖Blueprint來分模塊組織管理。

3.2.1 藍圖的特點

藍圖實際可以理解為是一個存儲一組視圖方法的容器對象,其具有如下特點:

  • 一個應用可以具有多個Blueprint
  • 可以將一個Blueprint註冊到任何一個未使用的URL下比如 “/user”、“/goods”
  • Blueprint可以單獨具有自己的模板、靜態文件或者其它的通用操作方法,它並不是必須要實現應用的視圖和函數的
  • 在一個應用初始化時,就應該要註冊需要使用的Blueprint

但是一個Blueprint並不是一個完整的應用,它不能獨立於應用運行,而必須要註冊到某一個應用中。

3.2.2 藍圖的使用方式

使用藍圖可以分為三個步驟

  1. 創建一個藍圖對象

    # 1.創建藍圖對象,兩個參數分別為藍圖名稱(name)和import_name
    user_bp =Blueprint('user',__name__)
    
  2. 在這個藍圖對象上進行操作,註冊路由,指定靜態文件夾,註冊模版過濾器

    # 2.藍圖對象註冊路由
    @user_bp.get("/user")
    def user_profile():
        return "user_profile"
    
  3. 在應用對象上註冊這個藍圖對象

    # 3.在app中註冊藍圖對象
    app.register_blueprint(user_bp)
    

3.2.3 單文件藍圖

可以將創建藍圖對象與定義視圖放到一個文件中 ,也就是按照上面看到的代碼

image-20230802140637099

image-20230802140553512

3.2.4 目錄(包)藍圖

對於一個打算包含多個文件的藍圖,通常將創建藍圖對象放到Python包的__init__.py文件中

--------- project # 工程目錄
  |------ main.py # 啟動文件
  |------ user  #用戶藍圖
  |  |--- __init__.py  # 此處創建藍圖對象
  |  |--- view.py

image-20230802141952535

image-20230802141900021

註意:如果不在__init__.py中導入view.py文件,則會導致404錯誤

3.2.5 擴展用法

1 指定藍圖的url首碼

在應用中註冊藍圖時使用url_prefix參數指定首碼

app.register_blueprint(user_bp,url_prefix="/user")

image-20230802142319519

image-20230802142353665

2 藍圖內部靜態文件

和應用對象不同,藍圖對象創建時不會預設註冊靜態目錄的路由。需要我們在 創建時指定 static_folder 參數。

下麵的示例將藍圖所在目錄下的user_admin目錄設置為靜態目錄

user_bp = Blueprint("user",__name__,static_folder="user_admin")
app.register_blueprint(user_bp,url_prefix="/user")

image-20230802142700708

image-20230802142859825

現在就可以使用/user/user_admin/<path:filename>訪問user_admin目錄下的靜態文件了。

也可通過static_url_path改變訪問路徑

user_bp = Blueprint("user",__name__,static_folder="user_admin",static_url_path="static")

app.register_blueprint(user_bp,url_prefix="/user")

image-20230802143100899

image-20230802143125247

3 藍圖內部模板目錄

藍圖對象預設的模板目錄為系統的模版目錄,可以在創建藍圖對象時使用template_folder關鍵字參數設置模板目錄

user_bp = Blueprint("user",__name__,
                    static_folder="user_admin",
                    static_url_path="static",
                    template_folder="templates")

image-20230802143347409

4 請求與響應

4.1 處理請求

請求攜帶的數據可能出現在HTTP報文中的不同位置,需要使用不同的方法來獲取參數。

4.1.1. URL路徑參數(動態路由)

Flask不同於Django直接在定義路由時編寫正則表達式的方式,而是採用轉換器語法:

# 這裡本質上進行的是正則匹配
@app.route('/users/<user_id>')
def user_info(user_id):
    print(type(user_id))
    return 'hello user {}'.format(user_id)

image-20230802144154719

image-20230802144228255

此處的<>即是一個轉換器,預設為字元串類型,即將該位置的數據以字元串格式進行匹配、並以字元串為數據類型類型、 user_id為參數名傳入視圖。

Flask也提供其他類型的轉換器

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

將上面的例子以整型匹配數據,可以如下使用:

@app.route('/users/<int:user_id>')
def user_info(user_id):
    print(type(user_id))
    return 'hello user {}'.format(user_id)

image-20230802145247249

自定義轉換器

如果遇到需要匹配提取/users/18512345678中的手機號數據,Flask內置的轉換器就無法滿足需求,此時需要自定義轉換器。

定義方法

自定義轉換器主要做3步

  1. 創建轉換器類,保存匹配時的正則表達式

    from werkzeug.routing import BaseConverter
    
    # 1.自定義匹配手機號的轉換器
    class PhoneConverter(BaseConverter):
        regex = "^1[3456789]\d{9}$"
    
    • 註意regex名字固定
  2. 註冊轉換器,將自定義的轉換器告知Flask應用

    # 2. 註冊轉換器
    app.url_map.converters["phone"] = PhoneConverter
    
  3. 使用轉換器:在使用轉換器的地方定義使用

    @app.get('/users/phone/<phone:phoneNum>')
    def getPhone(phoneNum):
        return f"你的手機號是:{phoneNum}"
    

    image-20230802150218370

image-20230802145935159

4.1.2. 其他參數

如果想要獲取其他地方傳遞的參數,可以通過Flask提供的request對象來讀取。

不同位置的參數都存放在request的不同屬性中

屬性 說明 類型
data 記錄請求的數據,並轉換為字元串 *
form 記錄請求中的表單數據 MultiDict
args 記錄請求中的查詢參數 MultiDict
cookies 記錄請求中的cookie信息 Dict
headers 記錄請求中的報文頭 EnvironHeaders
method 記錄請求使用的HTTP方法 GET/POST
url 記錄請求的URL地址 string
files 記錄請求上傳的文件 *

例如 想要獲取請求/articles?channel_id=1channel_id的參數,可以按如下方式使用:

@app.get("/request/change")
def getChangeId():
    changeId = request.args.get("change_id")
    return f"change_id = {changeId}"

image-20230802151050663

image-20230802151022966

上傳圖片

客戶端上傳圖片到伺服器,並保存到伺服器中

@app.post("/request/images")
def putImages():
    image = request.files.get("image")
    image.save("./Saber.png")
    return "圖片上傳成功"

image-20230802152107275

image-20230802152138309

4.2 處理響應

4.2.1 返回模板

使用render_template方法渲染模板並返回

# 其中template表示的是html模板的名稱,*kwargs是傳遞的參數
render_template(template,*kwargs)

實例:

image-20230802152929143

測試:

image-20230802153044679

4.2.2 重定向

from flask import redirect

@app.get("/redirectTest/")
def redirectTest():
    return redirect("https://www.baidu.com/")

image-20230802154405894

4.2.3 返回JSON

from flask import jsonify

@app.get("/jsonTest/")
def jsonTest():
    json_dict = {
        "user_id": 10086,
        "user_name": "張三",
        "user_age": 30
    }
    return jsonify(json_dict)

image-20230802154459235

4.2.4 自定義狀態碼和響應頭

1 元組方式

可以返回一個元組,這樣的元組必須是

 # 其中response為相應內容,status響應狀態碼,headers為響應頭的添加內容
 (response, status, headers)

的形式,且至少包含一個元素。 status 值會覆蓋狀態代碼, headers 可以是一個列表或字典,作為額外的消息標頭值。

# 第一種自定義響應頭的方式
@app.get("/demoTestOne/")
def demoTestOne():
    return ("狀態碼為 202",202)

image-20230802155324882

2 make_response方式

@app.get("/demoTestTwo/")
def demoTestTwo():
    resp = make_response("狀態碼為 201")
    resp.headers['name'] = "zhangsan"
    resp.status = 201
    return resp

image-20230802155550932

4.3 Cookie與Session

1 設置Cookie

@app.get("/setCookie/")
def setCookie():
    resp = make_response("set Cookie")
    resp.set_cookie("username","zhangsan")
    return resp

image-20230802161248574

2 設置Cookie有效期

# 設置Cookie有效期
@app.get("/setCTime")
def setCTime():
    resp = make_response("set cookie time")
    resp.set_cookie("username","zhangsan",max_age=180)
    return resp

image-20230802161434776

3 讀取Cookie

# 讀取Cookie
@app.get("/getCookie")
def getCookie():
    requ = request.cookies.get("username")
    return f"username:{requ}"

image-20230802161456889

4 刪除Cookie(實際是就是將有效期設置為0)

# 刪除Cookie
@app.get("/deleteCookie")
def deleteCookie():
    resp = make_response("delete Cookie")
    resp.delete_cookie("username")
    return resp

image-20230802161533713

4.3.2 Session

1 需要先設置SECRET_KEY

# 1 設置SECRET_KEY
class DefaultConfig(object):
    SECRET_KEY = "zhansganlisiwangu"
app.config.from_object(DefaultConfig)

2 設置Session

# 2 設置Session
from flask import session
@app.get("/setSession/")
def setSession():
    session['username'] = "username"
    return "set Session"

image-20230802162225274

3 讀取Session

@app.get("/getSession/")
def getSession():
    username = session.get("username")
    return f"get session username {username}"

這裡的Session並不是真正意義上的session,而是偽裝成Session的Cookie,因為它實際上並沒有將值存儲在伺服器上

image-20230802162259700

5 請求鉤子與上下文

5.1 異常處理

5.1.1 HTTP 異常主動拋出

  • abort 方法
    • 拋出一個給定狀態代碼的 HTTPException 或者 指定響應,例如想要用一個頁面未找到異常來終止請求,你可以調用 abort(404)。
  • 參數:
    • code – HTTP的錯誤狀態碼
# abort(404)
abort(500)

拋出狀態碼的話,只能拋出 HTTP 協議的錯誤狀態碼

from flask import abort

@app.get("/getExcetion")
def getExcetion():
    print("異常請求測試")
    abort(500)
    return "500異常測試"

image-20230803073419048

image-20230803073338242

5.1.2 捕獲錯誤

errorhandler 裝飾器

  • 註冊一個錯誤處理程式,當程式拋出指定錯誤狀態碼的時候,就會調用該裝飾器所裝飾的方法

參數:

  • code_or_exception – HTTP的錯誤狀態碼或指定異常

  • 例如統一處理狀態碼為500的錯誤給用戶友好的提示:

# 捕獲異常
@app.errorhandler(ZeroDivisionError)
def zero_division_error(e):
    return "除數不能為0"

@app.get("/zeroTest")
def zeroDivision():
    a = 10086/0
    return  f"結果是:{a}"

image-20230803073538896

  • 捕獲指定異常
@app.errorhandler(500)
def errorCode500():
    return "嗚嗚嗚,伺服器出錯了,請稍後訪問"

@app.get("/getExcetion")
def getExcetion():
    print("異常請求測試")
    abort(500)
    return "500異常測試"

image-20230803073750210

5.2 請求鉤子

5.2.1 請求鉤子概念

在客戶端和伺服器交互的過程中,有些準備工作或掃尾工作需要處理,比如:

  • 在請求開始時,建立資料庫連接;
  • 在請求開始時,根據需求進行許可權校驗;
  • 在請求結束時,指定數據的交互格式;

為了讓每個視圖函數避免編寫重覆功能的代碼,Flask提供了通用設施的功能,即請求鉤子。


請求鉤子是通過裝飾器的形式實現,Flask支持如下三種請求鉤子(before_first_request已經被廢止):

1 before_request

  • 在每次請求前執行
  • 如果在某修飾的函數中返回了一個響應,視圖函數將不再被調用

2 after_request

  • 如果沒有拋出錯誤,在每次請求後執行
  • 接受一個參數:視圖函數作出的響應
  • 在此函數中可以對響應值在返回之前做最後一步修改處理
  • 需要將參數中的響應在此參數中進行返回

3 teardown_request

  • 在每次請求後執行
  • 接受一個參數:錯誤信息,如果有相關錯誤拋出

5.2.2 代碼測試

# 在每一次請求之前調用,這時候已經有請求了,可能在這個方法裡面做請求的校驗
# 如果請求的校驗不成功,可以直接在此方法中進行響應,直接return之後那麼就不會執行視圖函數
@app.before_request
def before_request():
    print("before_request")
# 在執行完視圖函數之後會調用,並且會把視圖函數所生成的響應傳入,可以在此方法中對響應做最後一步統一的處理
@app.after_request
def after_request(response):
    print("after_request")
    response.headers["Content-Type"] = "application/json"
    return response
# 請每一次請求之後都會調用,會接受一個參數,參數是伺服器出現的錯誤信息
@app.teardown_request
def teardown_request(response):
    print("teardown_request")
# 測試請求
@app.route('/testRequest')
def index():
    return 'index'

image-20230803074816568

請求時列印的內容,可以看出,三個鉤子函數都被調用

image-20230803075042236

5.3 上下文

上下文:即語境,語意,在程式中可以理解為在代碼執行到某一時刻時,根據之前代碼所做的操作以及下文即將要執行的邏輯,可以決定在當前時刻下可以使用到的變數,或者可以完成的事情。

Flask中有兩種上下文,請求上下文和應用上下文

Flask中上下文對象:相當於一個容器,保存了 Flask 程式運行過程中的一些信息。

5.3.1 請求上下文(request context)

在 flask 中,可以直接在視圖函數中使用 request 這個對象進行獲取相關數據,而 request 就是請求上下文的對象,保存了當前本次請求的相關數據,請求上下文對象有:request、session

1 request

  • 封裝了HTTP請求的內容,針對的是http請求。舉例:user = request.args.get('user'),獲取的是get請求的參數。
# request獲取請求參數
@app.get("/requestContext")
def requestContext():
    user = request.args.get('user')
    return f"你的名字是:{user}"

image-20230803080144756

2 session

  • 用來記錄請求會話中的信息,針對的是用戶信息。舉例:session['name'] = user.id,可以記錄用戶信息。還可以通過session.get('name')獲取用戶信息。
# session存儲用戶id
@app.get("/setRequestSession")
def setRequestSession():
    user_id = "zhangsan"
    session['name'] = user_id
    return "Session 設置成功"

# 獲取Session
@app.get("/getRequestSession")
def setRequestSession():
    username = session.get('name')
    return f"你的名字是:{username}"

image-20230803080224212

image-20230803080257424

5.3.2 應用上下文(application context)

它的字面意思是 應用上下文,但它不是一直存在的,它只是request context 中的一個對app的代理(人),所謂local proxy。它的作用主要是幫助 request 獲取當前的應用,它是伴 request 而生,隨 request 而滅的。

應用上下文對象有:current_appg

1 current_app

應用程式上下文,用於存儲應用程式中的變數,可以通過current_app.name列印當前app的名稱,也可以在current_app中存儲一些變數,例如:

  • 應用的啟動腳本是哪個文件,啟動時指定了哪些參數
  • 載入了哪些配置文件,導入了哪些配置
  • 連了哪個資料庫
  • 有哪些public的工具類、常量
  • 應用跑再哪個機器上,IP多少,記憶體多大

示例

創建current_app_demo.py

from flask import current_app

app1 = Flask(__name__)
app2 = Flask(__name__)

app1.redis_cli = 'app1 redis client'
app2.redis_cli = 'app2 redis client'

@app1.route('/route11')
def route11():
    # current_app獲取的是當前正在使用的app
    return current_app.redis_cli

@app2.route('/route21')
def route21():
    return current_app.redis_cli

運行

set FLASK_APP=main:app1
flask run

image-20230803081216087

set FLASK_APP=main:app2
flask run

image-20230803081252740

作用

current_app 就是當前運行的flask app,在代碼不方便直接操作flask的app對象時,可以操作current_app就等價於操作flask app對象,而不會出現app調用app對象自身導致的迴圈依賴問題

2 g對象

g 作為flask程式全局的一個臨時變數,充當中間媒介的作用,我們可以通過它在一次請求調用的多個函數間傳遞一些數據。每次請求都會重設這個變數。

示例

from flask import g
def query():
    user_id = g.user_id
    user_name = g.user_name
    return f"userid={user_id},name={user_name},已執行內部函數"

@app.post("/getUser/")
def get_user():
    userid = request.args.get("userid")
    username = request.args.get("username")
    g.user_id = userid
    g.user_name = username
    text = query()
    return text

image-20230803082805314

5.3.3 app_context 與 request_context

思考

在Flask程式未運行的情況下,調試代碼時需要使用current_appgrequest這些對象,該如何進行測試。

1 app_context

app_context為我們提供了應用上下文環境,允許我們在外部使用應用上下文current_appg`

可以通過with語句進行使用

>>> from flask import Flask
>>> app = Flask('')
>>> app.redis_cli = 'redis client'
>>> 
>>> from flask import current_app
>>> current_app.redis_cli   # 錯誤,沒有上下文環境
報錯
>>> with app.app_context():  # 藉助with語句使用app_context創建應用上下文
...     print(current_app.redis_cli)
...
redis client

image-20230803083511002

image-20230803083640479

2 request_context

request_context為我們提供了請求上下文環境,允許我們在外部使用請求上下文requestsession

可以通過with語句進行使用

>>> from flask import Flask
>>> app = Flask('')
>>> request.args  # 錯誤,沒有上下文環境
報錯
>>> environ = {'wsgi.version':(1,0), 'wsgi.input': '', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/', 'SERVER_NAME': 'itcast server', 'wsgi.url_scheme': 'http', 'SERVER_PORT': '80'}  # 模擬解析客戶端請求之後的wsgi字典數據
>>> with app.request_context(environ):  # 藉助with語句使用request_context創建請求上下文
...     print(request.path)

image-20230803083952782

6 Flask-RESTful

6.1 起步

Flask-RESTful是用於快速構建REST API的Flask擴展。

6.1.1 安裝

pip install flask-restful

image-20230803084427913

6.1.2 Hello World

from flask import Flask
from flask_restful import Resource,Api

app = Flask(__name__)
api = Api(app)

class HelloWordResource(Resource):
    def get(self):
        return {"hello":"world"}
    def post(self):
        return {"msg":"post Hello,World"}

api.add_resource(HelloWordResource,"/hello")

# 也可以選擇flask run的啟動方式
if __name__=="__main__":
    app.run(debug=True)

image-20230803084936029

image-20230803085032910

6.2 關於視圖

6.2.1 為路由起名

通過endpoint參數為路由起名

# 這個名稱在後續會用到
api.add_resource(HelloWorldResource, '/', endpoint='HelloWorld')

image-20230803085231864

6.2.2 藍圖中使用

# 1 定義藍圖
user_bp = Blueprint('user',__name__,url_prefix="/user")
# 2 api配置藍圖
user_api = Api(user_bp)
# 3 app配置藍圖
app.register_blueprint(user_bp)
# 4 定義藍圖請求
class UserBlueResource(Resource):
    def get(self):
        context = {
            "massage":2001,
            "data":{
                "name":"zhangsan",
                "age":16
            }
        }
        return context
    def post(self):
        context = {
            "massage":2001,
            "data":{
                "name":"This is post Man",
                "age":"*****(查看請充值vip)"
            }
        }
        return context
# 5 配置api路由
user_api.add_resource(UserBlueResource,"/blueUser")

image-20230803090111115

image-20230803090140372

6.2.3 裝飾器

使用method_decorators添加裝飾器

為類視圖中的所有方法添加裝飾器

def decorator1(func):
    def wrapper(*args, **kwargs):
        print('裝飾器1正在執行')
        return func(*args, **kwargs)
    return wrapper


def decorator2(func):
    def wrapper(*args, **kwargs):
        print('裝飾器2正在執行')
        return func(*args, **kwargs)
    return wrapper

class DemoRequest(Resource):
    method_decorators = [decorator1,decorator2]
    def get(self):
        context = {
            "msg":200,
            "data":{
                "text":"一切正常"
            }
        }
        return context

    def post(self):
        context = {
            "msg":200,
            "data":{
                "text":"I am PostMax"
            }
        }
        return context
api.add_resource(DemoRequest,"/demo")

image-20230803091202637

image-20230803091147495


為類視圖中不同的方法添加不同的裝飾器

  class DemoResource(Resource):
      method_decorators = {
          'get': [decorator1, decorator2],
          'post': [decorator1]
      }

      # 使用了decorator1 decorator2兩個裝飾器
      def get(self):
          return {'msg': 'get view'}

      # 使用了decorator1 裝飾器
      def post(self):
          return {'msg': 'post view'}

      # 未使用裝飾器
      def put(self):
          return {'msg': 'put view'}

get請求測試

image-20230803091338663

image-20230803091346891

post請求測試

image-20230803091401420

image-20230803091408854

put請求測試

image-20230803091427366

image-20230803091440332

6.3 關於請求

6.3.1 概述

Flask-RESTful 提供了RequestParser類,用來幫助我們檢驗和轉換請求數據。

6.3.2 使用步驟:

  1. 創建RequestParser對象

  2. RequestParser對象中添加需要檢驗或轉換的參數聲明

  3. 使用parse_args()方法啟動檢驗處理

  4. 檢驗之後從檢驗結果中獲取參數時可按照字典操作或對象屬性操作

    args.rate
    或
    args['rate']
    

6.3.3 參數說明

1 required

描述請求是否一定要攜帶對應參數,預設值為False

  • True 強制要求攜帶

    若未攜帶,則校驗失敗,向客戶端返回錯誤信息,狀態碼400

  • False 不強制要求攜帶

    若不強制攜帶,在客戶端請求未攜帶參數時,取出值為None

from flask_restful.reqparse import RequestParser
class rqparseRequest(Resource):
    # 1 required 參數測試
    def get(self):
        rqp = RequestParser()
        # 強制要求攜帶該參數
        rqp.add_argument("user",required=True)
        args = rqp.parse_args()
        return {"message":200,"data":{"user":args.user}}
api.add_resource(rqparseRequest,"/rpone")

image-20230803094203606

image-20230803094243865

2 help

參數檢驗錯誤時返回的錯誤描述信息

from flask_restful.reqparse import RequestParser
class rqparseRequest(Resource):
    # 2 help參數測試
    def post(self):
        rqp = RequestParser()
        # 強制要求攜帶該參數
        rqp.add_argument("user",required=True,help="沒有user參數")
        args = rqp.parse_args()
        return {"message":200,"data":{"user":args.user}}
api.add_resource(rqparseRequest,"/rpone")

image-20230803094415164

image-20230803094335761

3 action

描述對於請求參數中出現多個同名參數時的處理方式

  • action='store' 保留出現的第一個, 預設
  • action='append' 以列表追加保存所有同名參數的值
from flask_restful.reqparse import RequestParser
class rqparseRequest(Resource):
    # 3 action參數測試
    def put(self):
        rp = RequestParser()
        rp.add_argument("user",required=True,action="append")
        args = rp.parse_args()
        return {"message": 200, "data": {"user": args.user}}
api.add_resource(rqparseRequest,"/rpone")

image-20230803094604994

4 type

描述參數應該匹配的類型,可以使用python的標準數據類型string、int,也可使用Flask-RESTful提供的檢驗方法,還可以自己定義

  • 標準類型

    from flask_restful.reqparse import RequestParser
    class rqparseRequest(Resource):
        # 4 type參數測試
        def delete(self):
            rp = RequestParser()
            rp.add_argument("user",required=True,type=int)
            args = rp.parse_args()
            return {"message": 200, "data": {"user": args.user}}
    api.add_resource(rqparseRequest,"/rpone")
    

image-20230803094818592

image-20230803094853088

  • Flask-RESTful提供

    檢驗類型方法在flask_restful.inputs模塊中

    • url

    • regex(指定正則表達式)

      from flask_restful import inputs
      
      class rqparseRequestTwo(Resource):
          # Flask指定的檢驗格式
          def get(self):
              rp = RequestParser()
              rp.add_argument('user', type=inputs.regex(r'^1[3-9]\d{9}$'))
              args = rp.parse_args()
              return {"message": 200, "data": {"user": args.user}}
      api.add_resource(rqparseRequestTwo,"/rptwo")
      

    image-20230803095352692

    image-20230803095431384

    • natural 自然數0、1、2、3...

    • positive 正整數 1、2、3...

    • int_range(low ,high) 整數範圍

      rp.add_argument('a', type=inputs.int_range(1, 10))
      
    • boolean

  • 自定義

    def mobile(mobile_str):
        """
        檢驗手機號格式
        :param mobile_str: str 被檢驗字元串
        :return: mobile_str
        """
        if re.match(r'^1[3-9]\d{9}$', mobile_str):
            return mobile_str
        else:
            raise ValueError('{} is not a valid mobile'.format(mobile_str))
    
    rp.add_argument('a', type=mobile)
    

5 location

描述參數應該在請求數據中出現的位置

# Look only in the POST body
parser.add_argument('name', type=int, location='form')

# Look only in the querystring
parser.add_argument('PageSize', type=int, location='args')

# From the request headers
parser.add_argument('User-Agent', location='headers')

# From http cookies
parser.add_argument('session_id', location='cookies')

# From json
parser.add_argument('user_id', location='json')

# From file uploads
parser.add_argument('picture', location='files')

也可指明多個位置

parser.add_argument('text', location=['headers', 'json'])

測試

from flask_restful import inputs

class rqparseRequestTwo(Resource):
    # location測試
    def post(self):
        parser = RequestParser()
        # form表單
        parser.add_argument('name', type=int, location='form')
        # 位置參數
        parser.add_argument('PageSize', type=int, location='args')
        args = parser.parse_args()
        return {"message": 200, "data": {"name": args.name,"PageSize": args.PageSize}}
api.add_resource(rqparseRequestTwo,"/rptwo")

image-20230803100928742

6.4 關於響應

6.4.1 序列化數據

Flask-RESTful 提供了marshal工具,用來幫助我們將數據序列化為特定格式的字典數據,以便作為視圖的返回值。

# 1 導包
from flask_restful import Resource,fields,marshal_with,marshal
# 2 定義類
class Book(object):
    def __init__(self,bookName,author):
        self.bookName = bookName
        self.author = author
# 3 定義模板
resource_fields = {
    'bookName':fields.String,
    "author":fields.String
}

# 4 定義返回函數
class BookTodo(Resource):
    # 使用裝飾器實現
    @marshal_with(resource_fields,envelope="context")
    def get(self):
        # 對象無法直接返回,這個裝飾器相當於將對象序列化了
        book = Book("《射雕英雄傳》","金庸")
        return book
api.add_resource(BookTodo,"/booktodo")

image-20230803195429293

也可以不使用裝飾器的方式

# 不使用裝飾器,而是調用函數實現
def post(self):
    book = Book("《射雕英雄傳》","金庸")
    return marshal(book,resource_fields

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 海納思全稱是海思機頂盒NAS系統, 網站 https://www.ecoo.top/. 他們做的固件在 N2 NS-1 上應該是集成度做的最好的一個, 包含的功能很豐富, 除了常見的 Aria2, Transmission, Samba, 還集成了命令行, 網盤和筆記等. 適合想直接刷機使用, 不喜... ...
  • 一.前言 從上個世紀到現在,工程師們在優化伺服器性能的過程中,提出了各種不同的io模型,比如非阻塞io,io復用,信號驅動式io,非同步io。具體io模型在不同平臺上的實現也不一樣,比如io復用在bsd上可以由kqueue實現,在solaris系統上可以由/dev/poll實現。為了實現系統的可移植性 ...
  • 分庫分表是大型互聯網應用經常採用的一種數據層優化方案,常見的分庫分表中間件如 sharding-jdbc、mycat 都已經比較成熟,基本上可以應對我們一般的分庫分表需求。 做過分庫分表的同學應該知道,在給業務系統做分庫分表改造過程中,難的不是如何使用這些組件進行分庫分表,而是如何將非分庫分表的系... ...
  • 因歷史遺留原因,接手的項目沒有代碼提醒/格式化,包括 eslint、pretttier,也沒有 commit 提交校驗,如 husky、commitlint、stylelint,與其期待自己或者同事的代碼寫得完美無缺,不如通過一些工具來進行規範和約束。 ### eslint eslint 是一個代碼 ...
  • # 引言 這幾天幫朋友忙,用了一周時間,高仿了一個釘釘審批流。這個東西會有不少朋友有類似需求,就分享出來,希望能有所幫助。為了方便朋友的使用,設計製作的時候,儘量做到節點配置可定製,減少集成成本。如果您的項目有審批流需求,這個項目可以直接拿過去使用。React初學者也可以把本項目當做研讀案例,學習並 ...
  • ![](https://img2023.cnblogs.com/blog/3076680/202308/3076680-20230804112759115-773698620.png) # 1. 配置服務 ## 1.1. 配置服務本身就是分散式資料庫 ### 1.1.1. 像ZooKeeper和et ...
  • 隨著硬體技術的飛速發展,多核處理器已經成為計算設備的標配,這使得開發人員需要掌握併發編程的知識和技巧,以充分發揮多核處理器的潛力。然而併發編程並非易事,它涉及到許多複雜的概念和原理。為了更好地理解併發編程的內在機制,需要深入研究記憶體模型及其在併發編程中的應用。本文將主要以 Java 記憶體模型來探討並 ...
  • 最近看到一個冷門的資料庫管理工具:**slashbase**。 這個工具是開源免費的,由於開源不久,目前才900+的Star,但用下來還是非常不錯的,DD覺得這款工具還是非常有潛力的,所以給大家推薦一下。 ## 主要特性 [**slashbase**](https://blog.didispace. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...