1. 概述
基於flask框架構建web,一般會使用sqlchemy(在flask中使用sqlchemy可以參考這里)作為數據庫引擎。
這樣業務的邏輯就可以做到不跟具體的數據庫類型相耦合,具體后端業務是使用那種數據庫就全憑業務需要了。
但是數據表結構並不一定是一成不變的,可能隨着業務的需要表的結構經常會變換。面對這種情況,單純刪除之前的表,
重新再建新的表會導致數據的丟失,如果自己遷移又比較麻煩。以為,自己遷移的話,可能只能切到比較新的版本,但是
想要回滾到之前的版本幾乎是不可能的,這樣涉及到使用數據庫遷移工具了。
針對flask,有兩個比較重要的數據庫遷移工具:flask migrate和alembic。flask migrate是基於alembic,但是個人
感覺flask migrate不夠靈活,而且使用alembic還是比較方便的。所以,我這邊是直接使用alembic來做為數據庫遷移工具的。
首先,稍微介紹下alembic,alembic是sqlchemy作者一手締造的,對sqlchemy的兼容性肯定是其他組件根本無法媲美的。
2. 安裝
安裝alembic還是蠻方便的,直接使用python安裝工具pip就可以了,具體命令如下:
sudo pip install alembic
3. 初始化
回到flask application所處目錄,執行如下命令:
alembic init alembic
執行成功之后,就能在當前目錄看到兩個比較重要的文件:alembic.ini文件和alembic目錄。
alembic.ini保存的是alembic的配置信息,而數據庫版本信息的記錄是在alembic目錄下。
alembic目錄的機構如下:
[root@localhost alembic]# ls -trlh total 16K -rw-r--r-- 1 root root 38 May 11 19:36 README -rw-r--r-- 1 root root 494 May 11 19:36 script.py.mako -rw-r--r-- 1 root root 2.1K May 12 02:43 env.py drwxr-xr-x 2 root root 4.0K May 12 18:53 versions
這塊起作用的有兩個,一個是env.py文件以及versions目錄。
env.py記錄着跟環境有關的一些信息,比較起作用的是target_metadata這個字段,后面在介紹使用的時候會提到。
versions目錄下面是記錄當前數據庫所有版本,以及對應操作的python文件。
每個文件內容大致如下:
"""empty message Revision ID: 27c6a30d7c24 Revises: None Create Date: 2011-11-08 11:40:27.089406 """ # revision identifiers, used by Alembic. revision = '27c6a30d7c24' down_revision = None from alembic import op import sqlalchemy as sa def upgrade(): pass def downgrade(): pass
revision字段記錄的是當前文件代表的版本,初始時down_revision為None。具體在使用過程中一般指向的是上一個版本,具體
在回滾過程中非常有用。默認情況下upgrade和downgrade都會空。
在數據庫升級或者回滾過程中必須要重寫這這個函數,如果要升級就需要重寫upgrade函數,回滾就需要重寫downgrade函數。
4. 一個簡答的例子
首先必須更改alembic.ini文件中的sqlalchemy.url字段,改為你目前在使用的數據路徑就OK了。
此處,我是改為:
sqlalchemy.url = sqlite:////home/dashuju/admin_db.sqlite
這個文件其他字段可以暫時不用更改,目前的設置就可以使用了。
更改alembic目錄下的env.py文件,主要是設置target_metadata這個字段:
import sys sys.path.append('.') from admin_app import db target_metadata = db.metadata
admin_app是flask application的文件名,db是在flask_app定義的全局變量,
具體初始化為:db = SQLAlchemy(app)
更改下versions目錄下的當前版本py文件,並根據對應的upgrade和downgrade函數,具體代碼如下:
def upgrade(): op.create_table( 'users', sa.Column('id', sa.Integer, primary_key=True), sa.Column('name', sa.String(50), nullable=False), sa.Column('description', sa.Unicode(200)), ) def downgrade(): op.drop_table('users')
執行:
alembic upgrade head
指令來升級數據庫,查看對應的數據庫,可以看到數據庫中多了一個users表。
查看versions目錄下的文件,會發現多了一個py文件。可以在flask application所在目錄執行:
alembic current來查看當前數據庫所處版本,也可以使用alembic history來查看數據庫變更的歷史記錄。
如果想要回滾,也可以使用alemibic downgrade -1指令來回滾數據庫到之前的版本。
更改表結構
對於想要更改表結構,比如插入column或者刪除column,刪除column可能特殊些,所以要講下:
插入行,一般如下:
op.add_column('users', sa.Column('id', sa.INTEGER(), nullable=True))
刪除行,可能特殊些,具體如下:
with op.batch_alter_table('users') as batch_op: batch_op.drop_column('id')
想要刪除多列,可以在with語句下增加多行就可以了,否則會報錯:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) near "DROP": syntax error [SQL: u'ALTER TABLE posts DROP COLUMN XXX']
5. 后續
alembic的使用還在繼續,剛接觸,記錄下。