与sqlalchemy_utils一起使用alembic时遇到麻烦

时间:2015-05-08 20:29:26

标签: python sqlalchemy alembic

在我的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?

4 个答案:

答案 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迁移版本文件中,并相应地编辑升级功能。

就像在这里https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.choice

答案 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,都不会发生这种情况。

对于所有这些情况,您都必须进入迁移脚本并手动修复有问题的行。