在我的sqlalchemy模型中,我使用sqlalchemy_utils'choicetype:
id = db.Column(db.Integer, primary_key=True)
code = db.Column(db.Integer, nullable=True)
level = db.Column(mytypes.types.ChoiceType(LEVEL))
我按照此处所述做了所有事情http://alembic.readthedocs.org/en/latest/autogenerate.html#autogen-module-prefix。在我的模型中,我从我的模块mytypes.types中导入了choicetype:
from sqlalchemy_utils.types.choice import ChoiceType
,在alembic / env.py中添加了上下文
context.configure(
connection=connection,
target_metadata=target_metadata,
user_module_prefix="mytypes.types."
# ...
)
,并在script.py.mako
中import mytypes.types
。问题是当我修改我的模型时,我得到了一些东西 像这样
from alembic import op
import sqlalchemy as sa
import mytypes.types
def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('logging', sa.Column('level', mytypes.types.ChoiceType(length=255), nullable=True))
### end Alembic commands ###
为什么alembic没有将“LEVEL”参数传递给choicetype以及它为什么传递length = 255?
答案 0 :(得分:5)
针对此问题,我已经提出了一种更加自动化的解决方案。在我的env.py中,在功能run_migrations_online()中,我添加了一个自定义渲染器,用于处理sqlalchemy_utils类型。我只用ChoiceType和UUIDType进行了测试,但是它们对我有用。
因此在env.py和自定义渲染功能中:
def render_item(type_, obj, autogen_context):
"""Apply custom rendering for selected items."""
if type_ == "type" and obj.__class__.__module__.startswith("sqlalchemy_utils."):
autogen_context.imports.add(f"import {obj.__class__.__module__}")
if hasattr(obj, "choices"):
return f"{obj.__class__.__module__}.{obj.__class__.__name__}(choices={obj.choices})"
else:
return f"{obj.__class__.__module__}.{obj.__class__.__name__}()"
# default rendering for other objects
return False
然后我修改了现有上下文配置以使用它:
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
render_item=render_item,
process_revision_directives=process_revision_directives,
**current_app.extensions["migrate"].configure_args,
)
这意味着当我使用新的sqlalchemy_utils运行manage.py db migrate
时,它将正确导入模块并将类型添加到migrarions中。我为ChoiceType的choices属性添加了特殊处理。可能需要针对更多类型/属性进行扩展。
答案 1 :(得分:3)
我通过手动修改它来修复它
mytypes.types.ChoiceType(length=255)
至
mytypes.types.ChoiceType(MyEnum)
并导入它。
答案 2 :(得分:0)
Alembic和SqlAlchemy-utils不是像我们期望的那样的朋友。因此,请务必将模型文件导入Alembic迁移版本文件中,并相应地编辑升级功能。
答案 3 :(得分:0)
length不是ChoiceType的有效参数,Alembic将其传递为参数错误。 因此,您必须导入定义您的选项的Enum类,通常可以这样定义:
import Enum
class Role(Enum):
admin = 1
regular = 2
或包含元组的列表:
STATUS = [
('0', 'open'),
('1', 'closed')
]
,甚至直接在迁移文件中定义它们。 然后使用新更改重新运行迁移。
确保还将sqlalchemy_utils
库导入迁移文件。
Alemic无法与sqlalchemy_utils
很好地集成,并且会生成关于应如何定义自定义sqlalchemy_utils自定义字段的错误脚本。不仅对于ChoiceType,而且对于其他数据类型,例如PasswordType,都不会发生这种情况。
对于所有这些情况,您都必须进入迁移脚本并手动修复有问题的行。