python - 在 flask 迁移或 alembic 迁移中创建种子数据

标签 python flask flask-sqlalchemy alembic flask-migrate

如何在我的第一次迁移中插入一些种子数据?如果迁移不是最好的地方,那么最佳做法是什么?

"""empty message

Revision ID: 384cfaaaa0be
Revises: None
Create Date: 2013-10-11 16:36:34.696069

"""

# revision identifiers, used by Alembic.
revision = '384cfaaaa0be'
down_revision = None

from alembic import op
import sqlalchemy as sa


def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.create_table('list_type',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=80), nullable=False),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('name')
    )
    op.create_table('job',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('list_type_id', sa.Integer(), nullable=False),
    sa.Column('record_count', sa.Integer(), nullable=False),
    sa.Column('status', sa.Integer(), nullable=False),
    sa.Column('sf_job_id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(), nullable=False),
    sa.Column('compressed_csv', sa.LargeBinary(), nullable=True),
    sa.ForeignKeyConstraint(['list_type_id'], ['list_type.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    ### end Alembic commands ###

    # ==> INSERT SEED DATA HERE <==


def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('job')
    op.drop_table('list_type')
    ### end Alembic commands ###

最佳答案

Alembic 的其中一项业务是 bulk_insert() .文档给出了以下示例(我已经包含了一些修复):

from datetime import date
from sqlalchemy.sql import table, column
from sqlalchemy import String, Integer, Date
from alembic import op

# Create an ad-hoc table to use for the insert statement.
accounts_table = table('account',
    column('id', Integer),
    column('name', String),
    column('create_date', Date)
)

op.bulk_insert(accounts_table,
    [
        {'id':1, 'name':'John Smith',
                'create_date':date(2010, 10, 5)},
        {'id':2, 'name':'Ed Williams',
                'create_date':date(2007, 5, 27)},
        {'id':3, 'name':'Wendy Jones',
                'create_date':date(2008, 8, 15)},
    ]
)

还要注意,蒸馏器有一个 execute()操作,就像 SQLAlchemy 中的普通 execute() 函数一样:您可以运行任何您想要的 SQL,如文档示例所示:

from sqlalchemy.sql import table, column
from sqlalchemy import String
from alembic import op

account = table('account',
    column('name', String)
)
op.execute(
    account.update().\
        where(account.c.name==op.inline_literal('account 1')).\
        values({'name':op.inline_literal('account 2')})
        )

请注意,用于创建在 update 语句中使用的元数据的表是直接在模式中定义的。这看起来像是中断了 DRY (不是您的应用程序中已经定义的表),但实际上是非常必要的。如果您尝试使用属于应用程序一部分的表或模型定义,那么当您在应用程序中对表/模型进行更改时,您将中断此迁移。您的迁移脚本应该一成不变:对模型 future 版本的更改不应更改迁移脚本。使用应用程序模型意味着定义将根据您 check out 的模型版本(很可能是最新版本)而改变。因此,您需要在迁移脚本中独立包含表定义。

要讨论的另一件事是您是否应该将种子数据放入作为自己的命令运行的脚本中(例如使用 Flask-Script 命令,如另一个答案所示)。这可以使用,但你应该小心它。如果您加载的数据是测试数据,那是一回事。但我将“种子数据”理解为应用程序正常工作所需的数据。例如,如果您需要在“roles”表中设置“admin”和“user”的记录。这些数据应该作为迁移的一部分插入。请记住,脚本仅适用于最新版本的数据库,而迁移将适用于您要迁移到或从中迁移的特定版本。如果您想要一个脚本来加载角色信息,您可能需要一个脚本用于每个版本的数据库,并为“角色”表提供不同的架构。

此外,通过依赖脚本,您会更难在迁移之间运行脚本(例如迁移 3->4 要求初始迁移中的种子数据在数据库中)。您现在需要修改 Alembic 的默认运行方式来运行这些脚本。这仍然没有忽略这些脚本必须随着时间而改变的问题,以及谁知道您从源代码管理中 checkout 的应用程序版本。

关于python - 在 flask 迁移或 alembic 迁移中创建种子数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19334604/

相关文章:

python - flask 迁移 : Alembic converting choices into 255

python 对 Flask-SQLAlchemy 中 AppenderBaseQuery 属性的赋值无效

python - 使用 Python 的 sqlite 文件名列表

Python JSON 不可哈希类型 : 'dict'

python - Flask 静态文件 Cache-Control

python - 如何在启动时在docker容器上运行多个命令?

python - Heroku、Flask 和 Python 套接字?

python - SQLAlchemy 中使用的 relationship() 函数是什么

python - 将 python MySQLdb 安装到 python3 而不是 python

python - 有谁知道内置函数 ord() 的缩写词?