# Sqlalchemy with Flask-Migrate [TOC] ### 簡單介紹 - 在上次的理解中,Sqlalchemy是`不允許修改表結構`,如果需要修改的話,需要刪除重建,但這在正式環境下是有問題的。所以`Sqlalchemy`團隊開發了`Alembic`,Flask團隊也開發出了`Flask-Migrate`(底層也是`Alembic`) ### 目錄結構 ![](https://i.imgur.com/mpDmSsk.png) ### Coding~ 1. 安裝Flask-Migrate ```shell pip install Flask-Migrate ``` 1. 建立Flask App ```python # repository/app.py from flask import Flask import config app = Flask(__name__) # 建立app # 關閉追蹤各種改變的信號 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 設定DB路徑 app.config['SQLALCHEMY_DATABASE_URI'] = \ f"postgresql://{config.DB_USER}:{config.DB_PASSWORD}@{config.DB_HOST}:5432/test" # app.config['SQLALCHEMY_ECHO'] = True # 設定連線池數量 app.config['SQLALCHEMY_POOL_SIZE'] = 8 # 連線池timeout時間 app.config['SQLALCHEMY_POOL_TIMEOUT'] = 3 ``` 3. 建立Model ```python # repository/models.py from flask_migrate import Migrate from flask_sqlalchemy import SQLAlchemy from sqlalchemy import func from repository.app import app # 建立db物件 db = SQLAlchemy(app) # 建立Migrate,為了使用command line來操作 migrate = Migrate(app, db) # 透過上面創建的db,來建立DB內對應的table class GoodInfo(db.Model): __tablename__ = 'good_info_test' id = db.Column(db.String(128), primary_key=True) name = db.Column(db.String(128), nullable=True) price = db.Column(db.BigInteger) create_time = db.Column(db.DateTime, server_default=func.now()) def __str__(self): return f"GoodInfo<id={self.id}, name={self.name}, price={self.price}>" def __repr__(self): return f"GoodInfo<id={self.id}, name={self.name}, price={self.price}>" ``` ### 使用Flask-Migrate 1. 初始化migrations資料夾 ```shell flask --app repository/models.py db init ``` 2. 根據db.Model的結構產生對應的SQL語法 - 會在`migrations/versions/`底下創建一個.py檔案(如下圖的7dca07870a72_.py) - 也會在DB創建alembic_version表,用來記錄當前的version版本(7dca07870a72) ```shell flask --app repository/models.py db migrate ``` - 7dca07870a72_.py截圖。檔案內有`upgrade()`、`downgrade()`,裡面有對應的SQL語法 ![](https://i.imgur.com/Jufzjdv.png) 3. 更新到DB - 觸發7dca07870a72_.py內的upgrade(),新增該table - alembic_version表也會把該version記錄起來 ```shell flask --app repository/models.py db upgrade ``` 4. 降版(後悔了) - 觸發7dca07870a72_.py內的downgrade(),刪除該table ```shell flask --app repository/models.py db downgrade ``` ### 特殊情境 - migrations/version底下已經有對應的版本了 ```shell flask --app repository/models.py db upgrade ``` - 一直migrate出不來可以用以下的方式試試看 ```shell flask --app repository/models.py db stamp head flask --app repository/models.py db migrate flask --app repository/models.py db upgrade ``` ### 參考 - [flask設定sql的參數](https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/) - [官方flask-migrate教學](https://flask-migrate.readthedocs.io/en/latest/) - https://hackmd.io/@shaoeChen/r1luGOkVf?type=view#tags-flask-flask_ext-python - https://medium.com/seaniap/python-web-flask-%E5%AF%A6%E4%BD%9C-flask-migrate%E6%9B%B4%E6%96%B0%E8%B3%87%E6%96%99%E5%BA%AB-a5ebc930422a