创建基础空迁移。空迁移可以为 迁移提供一个干净的起点。
(venv) c11> alembic revision -m "emptyinit"
Generating c11\alembic\versions\87eea99e5889_emptyinit.py ... done #在version创建了一个新的迁移脚本
如果你在代码的一个分支中修改数据类,那你可能还需要为alembic迁移 建立分支。
打开version\87eea99e5889_emptyinit.py,其中的信息:
"""emptyinit #我们刚才迁移时设定的名字
Revision ID: 87eea99e5889 #迁移的ID,也叫迁移级别
Revises:
Create Date:
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '87eea99e5889' #迁移的ID,也叫迁移级别
down_revision = None #上一个迁移的ID
branch_labels = None #所在分支
depends_on = None #本次迁移依赖的迁移?
def upgrade(): #这两个函数的内容我们可以自己定义
pass
def downgrade():
pass
upgrade(): 执行迁移时 改动数据库。
downgrade(): 撤销本次迁移,并把数据库恢复到先前的迁移步骤。
目前没有任何ORM数据类,也没有任何更改,所以upgrade和downgrade都是空的,运行他们不会产生任何影响。
将数据库升级到最新版本。
(venv) c11> alembic upgrade head
这里的输出会把 最新修订 之前的 每次修订都列出来。??
接下来就可以 在app里定义ORM模型类了,然后创建一个自动生成的迁移,并在 数据库中 创建关联表。app/db.py
添加类
#...
Base = declarative_base()
from sqlalchemy import Table, Column, Integer, Numeric, String, Boolean, DateTime, ForeignKey
from datetime import datetime
from sqlalchemy.orm import relationship, backref
class Cookie(Base):
__tablename__ = 'cookies'
cookie_id = Column(Integer(), primary_key=True)
cookie_name = Column(String(30), index=True)
cookie_recipe_url = Column(String(255))
cookie_sku = Column(String(55))
quantity = Column(Integer())
unit_cost = Column(Numeric(12,2))
自动创建迁移。在运行自动生成命令时,alembic会检查sqlalchemyBase的元数据Base.metadata(db.py里定义的表),将其与 当前数据库的所有表进行比较。如果有差异,它就会把差异标记为更改,并添加到 迁移文件的upgrade()里面。见下面迁移文件内容
(venv) c11> alembic revision --autogenerate -m "add cookie model"
升级数据库(把表加到数据库)。这会把从 当前数据库状态 到 最新的迁移 之间的迁移 全部应用到数据库里。(这时才算是更新了数据库)
(venv) c11> alembic upgrade head
查看数据库,看更改是否生效
(venv) c11> sqlite3 alembictest.db
'sqlite3' 不是内部或外部命令...
还要先安装sqlite3。在https://www.sqlite.org/download.html下载 sqlite-tools-win32-*.zip 和 sqlite-dll-win32-*.zip 两个文件。创建文件夹 C:\sqlite3,把两个的内容都解压到sqlite3里。
添加 C:\sqlite3 到 PATH 环境变量:电脑》属性》高级系统设置》高级》环境变量》双击PATH》新建》输入C:\sqlite3
在cmd里测试是否安装成功
C: >sqlite3 SQLite version 3.35.5 2021-04-19 18:32:05 Enter ".help" for usage hints. Connected to a transient in-memory database. Use ".open FILENAME" to reopen on a persistent database. sqlite>
查看数据库,看更改是否生效
(venv) D:\alchemy\c11>sqlite3 alembictest.db #使用sqlite3命令 访问alembictest.db数据库
SQLite version 3.35.5 2021-04-19 18:32:05
Enter ".help" for usage hints.
sqlite> .tables #列出数据库中的表
alembic_version cookies
sqlite> .schema cookies #打印cookies表的结构
CREATE TABLE cookies (
cookie_id INTEGER NOT NULL,
cookie_name VARCHAR(30),
cookie_recipe_url VARCHAR(255),
cookie_sku VARCHAR(55),
quantity INTEGER,
unit_cost NUMERIC(12, 2),
PRIMARY KEY (cookie_id)
);
CREATE INDEX ix_cookies_cookie_name ON cookies (cookie_name);
本次的迁移文件 内容
"""add cookie model
Revision ID: 9f5bb26a626e
Revises: 87eea99e5889
Create Date:
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '9f5bb26a626e'
down_revision = '87eea99e5889'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
#表
op.create_table('cookies',
sa.Column('cookie_id', sa.Integer(), nullable=False),
sa.Column('cookie_name', sa.String(length=30), nullable=True),
sa.Column('cookie_recipe_url', sa.String(length=255), nullable=True),
sa.Column('cookie_sku', sa.String(length=55), nullable=True),
sa.Column('quantity', sa.Integer(), nullable=True),
sa.Column('unit_cost', sa.Numeric(precision=12, scale=2), nullable=True),
sa.PrimaryKeyConstraint('cookie_id')
)
#索引
op.create_index(op.f('ix_cookies_cookie_name'), 'cookies', ['cookie_name'], unique=False)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
#索引
op.drop_index(op.f('ix_cookies_cookie_name'), table_name='cookies')
#表
op.drop_table('cookies')
#这是正确的删除顺序,确保索引和表都删除。
# ### end Alembic commands ###
alembic的自动生成功能有 局限性,无法检测到:表 的名称变化、列 的名称变化、无明确名称的约束 等。这时候需要用手动
手动创建迁移
表 的名称变化。
先修改 db.py里 Cookie类的__tablename__
class Cookie(Base):
__tablename__ = 'new_cookies'
手动创建迁移。和自动的区别就是没有--autogenerate
(venv) c11> alembic revision -m "rename cookies to new_cookies"
编辑迁移文件。这就是叫手动的原因
def upgrade():
op.rename_table('cookies', 'new_cookies')
def downgrade():
op.rename_table('new_cookies', 'cookies')
升级数据库。
(venv) c11> alembic upgrade head
查看数据库,看更改是否生效
(venv) c11> sqlite3 alembictest.db
SQLite version 3.35.5 2021-04-19 18:32:05
Enter ".help" for usage hints.
sqlite> .tables
alembic_version new_cookies