Why real values in DB are ‘DRAFT’, ‘APPROVE’, ‘PUBLISHED’, but not draft, etc? I supposed there should be ENUM values, not names.
As Peter BaĊĦista’s already mentioned SQLAlchemy uses the enum names (DRAFT, APPROVE, PUBLISHED) in the database. I assume that was done because the enum values (“draft”, “approve”, …) can be arbitrary types in Python and they are not guaranteed to be unique (unless @unique
is used).
However since SQLAlchemy 1.2.3 the Enum
class accepts a parameter values_callable
which can be used to store enum values in the database:
status = db.Column(
db.Enum(PostStatus, values_callable=lambda obj: [e.value for e in obj]),
nullable=False,
default=PostStatus.DRAFT.value,
server_default=PostStatus.DRAFT.value
)
Why type poststatus was not created on DB-level automatically? In the similar migration it was.
I think basically you are hitting a limitation of alembic: It won’t handle enums on PostgreSQL correctly in some cases. I suspect the main issue in your case is Autogenerate doesn’t correctly handle postgresql enums #278.
I noticed that the type is created correctly if I use alembic.op.create_table
so my workaround is basically:
enum_type = SQLEnum(PostStatus, values_callable=lambda enum: [e.value for e in enum])
op.create_table(
'_dummy',
sa.Column('id', Integer, primary_key=True),
sa.Column('status', enum_type)
)
op.drop_table('_dummy')
c_status = Column('status', enum_type, nullable=False)
add_column('posts', c_status)