当我希望通过升级内的 Session 对象更改数据时,如何测试 alembic 迁移?
How do I test an alembic migration when I wish to alter the data via Session objects inside the upgrade?
我正在尝试让 alembic 为我执行数据库迁移。我对我的模型进行了更改,添加了两个新列,这些列将包含根据 table 中的当前行计算的数据。我真正想做的是弄清楚如何在迁移实际执行之前测试迁移将要执行的操作。我的理解是 --sql 参数允许我这样做。
当我尝试使用 --sql 进行升级以在实际执行之前测试迁移时,使用以下命令行:
alembic -c dev_alembic.ini upgrade --sql 3e0
我收到来自 alembic 的错误:
BEGIN TRANSACTION;
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL
);
GO
-- Running upgrade -> 3e076afb70e1
ALTER TABLE sipendpoint ADD extension VARCHAR(50) NULL;
GO
ALTER TABLE sipendpoint ADD home_site VARCHAR(5) NULL;
GO
Traceback (most recent call last):
File "/home/pgrace/venv/pyramid27/bin/alembic", line 9, in <module>
load_entry_point('alembic==0.7.6', 'console_scripts', 'alembic')()
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/config.py", line 439, in main
CommandLine(prog=prog).main(argv=argv)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/config.py", line 433, in main
self.run_cmd(cfg, options)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/config.py", line 416, in run_cmd
**dict((k, getattr(options, k)) for k in kwarg)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/command.py", line 165, in upgrade
script.run_env()
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/script.py", line 390, in run_env
util.load_python_file(self.dir, 'env.py')
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/util.py", line 243, in load_python_file
module = load_module_py(module_id, path)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/compat.py", line 79, in load_module_py
mod = imp.load_source(module_id, path, fp)
File "alembic/env.py", line 65, in <module>
run_migrations_offline()
File "alembic/env.py", line 44, in run_migrations_offline
context.run_migrations()
File "<string>", line 7, in run_migrations
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/environment.py", line 738, in run_migrations
self.get_context().run_migrations(**kw)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/migration.py", line 309, in run_migrations
step.migration_fn(**kw)
File "/home/pgrace/repo/stackcallrouterserver/alembic/versions/3e076afb70e1_add_extension_field_and_home_site_to_.py", line 48, in upgrade
for entry in DBSession.query(SIPEndpoint):
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2515, in __iter__
return self._execute_and_instances(context)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2528, in _execute_and_instances
close_with_result=True)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2519, in _connection_from_session
**kw)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 882, in connection
execution_options=execution_options)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 887, in _connection_for_bind
engine, execution_options)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 344, in _connection_for_bind
transaction = conn.begin()
AttributeError: 'MockConnection' object has no attribute 'begin'
这是有问题的迁移文件:
# revision identifiers, used by Alembic.
revision = '3e076afb70e1'
down_revision = None
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
import re
from scrserver.models import SIPEndpoint
from sqlalchemy.orm import (
scoped_session,
sessionmaker,
)
DBSession = scoped_session(sessionmaker(bind=op.get_bind()))
Base = declarative_base()
Base.metadata.bind = op.get_bind()
def sitecheck(x):
try:
return {
'1.2.3.4': "FOO",
'5.6.7.8': "BAR",
'9.10.11.12': "BAZ"
}
except KeyError:
return None
def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('sipendpoint', sa.Column('extension', sa.String(length=50), nullable=True))
op.add_column('sipendpoint', sa.Column('home_site', sa.String(length=5), nullable=True))
### end Alembic commands ###
for entry in DBSession.query(SIPEndpoint):
update=sa.update(SIPEndpoint).where(SIPEndpoint.addr==entry.addr).values(extension=entry.addr)
op.execute(update)
def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_column('sipendpoint', 'home_site')
op.drop_column('sipendpoint', 'extension')
### end Alembic commands ###
你不能运行这个:
for entry in DBSession.query(SIPEndpoint):
in --sql 模式,因为那是一个 SELECT 语句。在 --sql 模式下没有可用于 SELECT 的数据库。
无法对希望与数据库进行对话的脚本执行 "dry run",例如依赖于从 数据库 检索数据的脚本。 --sql 模式仅限于那些根本不需要交互的命令,例如CREATE、DROP 和 ALTER 语句,以及 极其有限 程度的 INSERT、UPDATE 和 DELETE 语句,它们必须以非常特殊的方式发出,这样它们就不会尝试请求有关信息操作。对于 INSERT,建议使用 bulk insert 样式,因为它旨在与 --sql 模式兼容。
我正在尝试让 alembic 为我执行数据库迁移。我对我的模型进行了更改,添加了两个新列,这些列将包含根据 table 中的当前行计算的数据。我真正想做的是弄清楚如何在迁移实际执行之前测试迁移将要执行的操作。我的理解是 --sql 参数允许我这样做。
当我尝试使用 --sql 进行升级以在实际执行之前测试迁移时,使用以下命令行:
alembic -c dev_alembic.ini upgrade --sql 3e0
我收到来自 alembic 的错误:
BEGIN TRANSACTION;
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL
);
GO
-- Running upgrade -> 3e076afb70e1
ALTER TABLE sipendpoint ADD extension VARCHAR(50) NULL;
GO
ALTER TABLE sipendpoint ADD home_site VARCHAR(5) NULL;
GO
Traceback (most recent call last):
File "/home/pgrace/venv/pyramid27/bin/alembic", line 9, in <module>
load_entry_point('alembic==0.7.6', 'console_scripts', 'alembic')()
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/config.py", line 439, in main
CommandLine(prog=prog).main(argv=argv)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/config.py", line 433, in main
self.run_cmd(cfg, options)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/config.py", line 416, in run_cmd
**dict((k, getattr(options, k)) for k in kwarg)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/command.py", line 165, in upgrade
script.run_env()
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/script.py", line 390, in run_env
util.load_python_file(self.dir, 'env.py')
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/util.py", line 243, in load_python_file
module = load_module_py(module_id, path)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/compat.py", line 79, in load_module_py
mod = imp.load_source(module_id, path, fp)
File "alembic/env.py", line 65, in <module>
run_migrations_offline()
File "alembic/env.py", line 44, in run_migrations_offline
context.run_migrations()
File "<string>", line 7, in run_migrations
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/environment.py", line 738, in run_migrations
self.get_context().run_migrations(**kw)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/alembic/migration.py", line 309, in run_migrations
step.migration_fn(**kw)
File "/home/pgrace/repo/stackcallrouterserver/alembic/versions/3e076afb70e1_add_extension_field_and_home_site_to_.py", line 48, in upgrade
for entry in DBSession.query(SIPEndpoint):
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2515, in __iter__
return self._execute_and_instances(context)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2528, in _execute_and_instances
close_with_result=True)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2519, in _connection_from_session
**kw)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 882, in connection
execution_options=execution_options)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 887, in _connection_for_bind
engine, execution_options)
File "/home/pgrace/venv/pyramid27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 344, in _connection_for_bind
transaction = conn.begin()
AttributeError: 'MockConnection' object has no attribute 'begin'
这是有问题的迁移文件:
# revision identifiers, used by Alembic.
revision = '3e076afb70e1'
down_revision = None
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
import re
from scrserver.models import SIPEndpoint
from sqlalchemy.orm import (
scoped_session,
sessionmaker,
)
DBSession = scoped_session(sessionmaker(bind=op.get_bind()))
Base = declarative_base()
Base.metadata.bind = op.get_bind()
def sitecheck(x):
try:
return {
'1.2.3.4': "FOO",
'5.6.7.8': "BAR",
'9.10.11.12': "BAZ"
}
except KeyError:
return None
def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('sipendpoint', sa.Column('extension', sa.String(length=50), nullable=True))
op.add_column('sipendpoint', sa.Column('home_site', sa.String(length=5), nullable=True))
### end Alembic commands ###
for entry in DBSession.query(SIPEndpoint):
update=sa.update(SIPEndpoint).where(SIPEndpoint.addr==entry.addr).values(extension=entry.addr)
op.execute(update)
def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_column('sipendpoint', 'home_site')
op.drop_column('sipendpoint', 'extension')
### end Alembic commands ###
你不能运行这个:
for entry in DBSession.query(SIPEndpoint):
in --sql 模式,因为那是一个 SELECT 语句。在 --sql 模式下没有可用于 SELECT 的数据库。
无法对希望与数据库进行对话的脚本执行 "dry run",例如依赖于从 数据库 检索数据的脚本。 --sql 模式仅限于那些根本不需要交互的命令,例如CREATE、DROP 和 ALTER 语句,以及 极其有限 程度的 INSERT、UPDATE 和 DELETE 语句,它们必须以非常特殊的方式发出,这样它们就不会尝试请求有关信息操作。对于 INSERT,建议使用 bulk insert 样式,因为它旨在与 --sql 模式兼容。