我将Alembic用作Python项目的数据库迁移工具。当我运行这样的命令时:
alembic revision -m "adding a column"
...它将添加一个名为alembic/versions/xxxxxxxxxxxx_adding_a_column.py
的新文件,其中xxxxxxxxxxxx
是随机生成的12位数字的哈希。
从使人可读的角度来看,这有点问题,因为这意味着当查看alembic/versions
目录时,所有文件将以随机顺序出现,而不是按顺序/按时间顺序显示订单。
Alembic中是否有任何选项可确保这些前缀修订版ID是连续的?我想我可以手动重命名文件,然后更新引用,但是我想知道是否已经有了类似的功能。
答案 0 :(得分:5)
听起来,您对顺序列出的修订文件更感兴趣,而不是顺序订购的修订ID。前者无需更改版本ID的生成方式即可实现。
运行alembic init alembic
时生成的alembic.ini
文件具有配置修订文件命名的部分:
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s
这是文档中的解释:
file_template-这是用于生成新文件的命名方案 迁移文件。当前值是默认值,因此已注释 出来。可用的令牌包括:
- %%(rev)s-版本ID
- %%(slug)s-从修订消息派生的截断的字符串
- %%(年)d,%%(月).2d,%%(天).2d,%%(小时).2d,%%(分钟).2d,%%(秒).2d-创建日期的组成部分,默认情况下为datetime.datetime.now(),除非还使用了时区配置选项。
因此,将file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
添加到alembic.ini
会将您的修订命名为2018-11-15_xxxxxxxxxxxx_adding_a_column.py
。
我发现了这个问题:https://bitbucket.org/zzzeek/alembic/issues/371/add-unixtime-stamp-to-start-of-versions向我指出了正确的方向。
A comment from from that issue:
时间戳不一定告诉您哪个文件是最新的, 因为允许分支。 “历史史”本来就是最好的 真理的来源。
因此,文件命名解决方案不能保证在目录中按逻辑顺序进行迁移(但会对IMO有所帮助)。可以针对具有顺序编号的情况提出相同的论点。
如果您确实想指定自己的修订标识符,请在命令行上使用--rev-id
标志。
例如:
alembic revision -m 'a message' --rev-id=1
生成了一个名为1_a_message.py
的文件:
"""a message
Revision ID: 1
Revises:
Create Date: 2018-11-15 13:40:31.228888
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '1'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
pass
def downgrade():
pass
因此,您绝对可以自己管理修订标识符。编写bash脚本以触发修订版本生成,并自动传递基于日期时间的rev_id
,例如--rev-id=<current datetime>
来控制目录中列出的顺序。
如果未指定修订版ID,则调用位于alembic.util.langhelpers
的函数rev_id()
:
def rev_id():
return uuid.uuid4().hex[-12:]
对rev_id()
的函数调用在该原始源中进行了硬编码,因此,如果没有猴子修补函数,将很难覆盖该行为。您可以创建一个库的派生分支,然后重新定义该函数,或者将其用于生成ID的函数配置为可配置的。
答案 1 :(得分:3)
在我的案例中,我找到了如何在没有额外 bash 脚本的情况下做到这一点,只是在 env.py 中使用了一些突变魔法。也许它会帮助某人。
Alembic 具有强大的 customizing generated revisions 功能,因此我们可以在此级别编写覆盖:
# env.py
def process_revision_directives(context, revision, directives):
# extract Migration
migration_script = directives[0]
# extract current head revision
head_revision = ScriptDirectory.from_config(context.config).get_current_head()
if head_revision is None:
# edge case with first migration
new_rev_id = 1
else:
# default branch with incrementation
last_rev_id = int(head_revision.lstrip('0'))
new_rev_id = last_rev_id + 1
# fill zeros up to 4 digits: 1 -> 0001
migration_script.rev_id = '{0:04}'.format(new_rev_id)
...
# then use it context.configure
context.configure(
...
process_revision_directives=process_revision_directives,
)
如果您还想将它用于没有 --autogenerate
创建的修订,您应该在 revision_environment
中将 alembic.ini
设置为 true
答案 2 :(得分:1)
我制作了一个脚本,用于根据####_
模式中已经存在的迁移数量自动增加修订号。这是TLDR版本。我将其保存为migrations.sh并更改第2行中的路径
#!/usr/bin/env bash
NEXT_ID=`ls kennel/db/versions/* | grep -P '/\d{4}_.*\.py$' | wc -l`
alembic revision -m $@ --rev-id=`printf "%04d" ${NEXT_ID}`
然后您可以像使用它一样
./migrations.sh migration_name
# or
./migrations.sh migration_name --autogenerate
完整的脚本包含文档,其默认值为--autogenerate
,可以使用--empty
标志将其禁用。
https://gist.github.com/chriscauley/cf0b038d055076a2a30de43526d4150e