文章目錄
一. 前情提要
1.本篇最後更新於 2020/10/16,如有部分內容失效,麻煩請告知,我會立即更新!
2.作者環境配置:
- Flask-SQLAlchemy == 2.4.4
- Python == 3.7.7
- Flask == 1.1.2
3.參考官方原文進行編譯: Configuration — Flask-SQLAlchemy Documentation (2.x)
二. 先建立簡單的 Flask 設置
底下是一個最基礎的 Flask 搭配 Flask-sqlalchemy 套件的參數設置,使用 app.config
來載入 Flask-sqlalchemy 的參數,設定上最少會需要放置 db
的連線位置,這個簡單的案例是使用 sqlite 來連線,接下來會再介紹其他的連線方式:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////absolute/path/to/foo.db'
db = SQLAlchemy(app)
@app.route('/')
def demo():
return 'Hello Flask'
if __name__ == "__main__":
app.run(debug=True)
三. 實用的 Flask-SQLAlchemy 參數設定
接下來會介紹三種很常會碰到的參數設定,分別是「資料庫連線參數」、「資料庫細節設定參數」和「用於 debug 的參數」
1. 資料庫連線參數
這邊僅列出筆者常用到的「MySQL」、「Postgres」和「SQLite」,如果想看其他資料庫連線可以參考:Connection URI Format
MySQL:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:[email protected]/db'
Postgres:
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql
://username:[email protected]/db'
SQLite:
#Unix/Mac (note the four leading slashes)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////absolute/path/to/foo.db'
#Windows (note 3 leading forward slashes and backslash escapes)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///C:\\absolute\\path\\to\\foo.db'
2. 資料庫細節設定參數
注意:以下這些參數寫法將會在 v3.0 被移除使用!
app.config['SQLALCHEMY_POOL_RECYCLE'] = 90
app.config['SQLALCHEMY_POOL_TIMEOUT'] = 900
app.config['SQLALCHEMY_POOL_SIZE'] = 10
app.config['SQLALCHEMY_MAX_OVERFLOW'] = 5
建議修改成如下:v2.4 開始新增 SQLALCHEMY_ENGINE_OPTIONS
,可以將 ENGINE 條件寫在裡面。
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
"pool_pre_ping": True,
"pool_recycle": 300,
'pool_timeout': 900,
'pool_size': 10,
'max_overflow': 5,
}
其中 pool_size
、pool_timeout
… 都蠻好理解的,這邊解釋一下 max_overflow
是指當 connection pool 連線都用光時,最多暫時額外再新增多少的連線數,以上面設定為例子:也就是說當超過 15 connections 時,新的使用者連線是會需要等待,直到超過設置的時間 (pool_timeout),則會連線失敗。
3. 用於 debug 的參數
第一種:SQLALCHEMY_ECHO
此參數預設是 False,當設定成 True 時,對資料庫的任何操作,都會在 console 顯示,如下範例是一個簡單的 ORM query,會將 Raw sql 指令 print 出來:
app.config['SQLALCHEMY_ECHO'] = True
db.session.query(Article).all()
>>> output:
2020-10-06 13:43:04,816 INFO sqlalchemy.engine.base.Engine {'param_1': 113}
2020-10-06 13:43:04,831 INFO sqlalchemy.engine.base.Engine SELECT count(*) AS count_1
FROM (SELECT article.id AS article_id, article.created_at AS article_created_at, article.updated_at AS article_updated_at, article.`textTitle` AS `article_textTitle`, article.`textDescriptionShort` AS `article_textDescriptionShort`, article.top AS article_top, article.thumbnail AS article_thumbnail, article.`testingResult` AS `article_testingResult`, article.aid AS article_aid
FROM article) AS anon_1
第二種:SQLALCHEMY_RECORD_QUERIES
還有另一種是將 SQLALCHEMY_RECORD_QUERIES
設為 True,指令
如下:
app.config['SQLALCHEMY_RECORD_QUERIES'] = True
然後可以在 after_request
後,使用 get_debug_queries 取得 query 的各種資訊,像是查詢時間、raw sql 語法、語法參數… 等。
這部分我有看過有些專案會寫當 query.duration 時間大於多少時,記錄在 log 的應用。
from flask_sqlalchemy import get_debug_queries
@app.after_request
def after_request(reponse):
for query in get_debug_queries():
print(query.statement) # SQL 查詢語法
print(query.parameters) # SQL 查詢語法的參數
print(query.duration) # 查詢花費的時間
print(query.context) # 請求的來源上下文
return reponse
@app.route('/test')
def test():
p = Person.query.filter_by(username='Max').first()
return 'ok'
四. 較少使用的配置參數
1. SQLALCHEMY_BINDS
此參數用於同時操作多個資料庫時使用,範例寫法如下:
app.config['SQLALCHEMY_BINDS'] = {
'users': 'mysqldb://localhost/users',
'appmeta': 'sqlite:////path/to/appmeta.db'
}
設置後,建立資料庫寫法如下:
>>> db.create_all(bind=['users'])
>>> db.create_all(bind='appmeta')
2. SQLALCHEMY_TRACK_MODIFICATIONS
Signal (信號) 是 Flask-SQLAlchemy 中較少人使用的功能,官方文件的說明也超少!甚至在 Flask-SQLAlchemy 官方文件中 3.x 的版本 提到,如果要使用 Signal event 建議直接使用 SQLALchemy (附上原文 In most cases, you’ll probably be better served by using SQLAlchemy events directly.)。
那如果有需要使用到 Flask 內建的 Signalling Support 的話,會需要將 SQLALCHEMY_TRACK_MODIFICATIONS
設置成 True,注意:設置後會消耗額外的記憶體。
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
而有關於 Flask Signal 功能可以參考此篇有更詳細的說明:说说 Flask 中的 Signal – SHUHARI 的博客
以及一個實際使用案例,可以參考這篇 Stack Overflow 有人有說明:python – SQLALCHEMY: how to use @events.listens_for in flask_sqlalchemy-SQLalchemy – Stack Overflow
最後~
▍回顧本篇介紹 Flask-Sqlalchemy 的參數介紹如下:
- SQLALCHEMY_DATABASE_URI
- SQLALCHEMY_ENGINE_OPTIONS
- SQLALCHEMY_ECHO
- SQLALCHEMY_RECORD_QUERIES
- SQLALCHEMY_BINDS
- SQLALCHEMY_TRACK_MODIFICATIONS
更多 Flask 教學相關閱讀:
▍關於 Flask 教學系列目錄:
▍關於 Flask 部署相關文章:
- 【Flask 教學系列】實作 GCP 部署 Flask + Nginx + uWSGI
- 【Flask 教學系列】實作 Flask + GitHub Action CI/CD
- 第一集:實作 Dockerfile + flask 教學 (附GitHub完整程式)
- 第二集:實作 Dockerfile + nginx + ssl + flask 教學 (附GitHub完整程式)
- 第三集:實作 Docker-compose (Flask+Nginx+PostgreSQL)
▍其他 Flask 相關教學:
- Flask 為甚麼需要 WSGI 與 Nginx
- Flask-SQLAlchemy 資料庫連線&設定入門 (一)
- Flask-JWT-Extended 實作
- 實作 Flask CORS
- 實作 Flask CSRF Protection
有關 Max行銷誌的最新文章,都會發佈在 Max 的 Facebook 粉絲專頁,如果想看最新更新,還請您按讚或是追蹤唷!