问题
At some point in the past I've run an alembic migration which creates a users
table like...
def upgrade():
...
op.create_table(
"users",
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
...
sa.Column("type", sa.Enum("Foo", "Bar", "Baz", name="usertype"), nullable=False),
...
)
...
...which automatically creates the enum named usertype
with the values "Foo", "Bar", "Baz"
.
Now, I want to make some other table which also references that same enum. e.g.,
def upgrade():
...
op.create_table('foobar',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
...
sa.Column('user_type', sa.Enum(< ???????? >), nullable=False),
...
)
What is the syntax to reference the existing enum?
I can't seem to find an answer in the docs: https://docs.sqlalchemy.org/en/13/core/type_basics.html#sqlalchemy.types.Enum
回答1:
I'd advise against that, as there is a difference between the model definition and the migration files. Keep in mind that if the enum ever changes, then Alembic needs to, firstly, detect that the enum has changed, and, secondly, know what the old values were. Otherwise, the only possible way to deal with it is to change the column type to something like VARCHAR
and then back to ENUM
, but that is a much more expensive and painful operation than just adding or removing one potential value.
Suppose we have the following enum:
class Animal(enum.Enum):
DOG = 'DOG'
CAT = 'CAT'
HAMSTER = 'HAMSTER'
For postgres
specifically, you can use sqlalchemy.dialects.postgres.ENUM
and pass it an existing enum:
animal = Column(ENUM(Animal), nullable=False)
But flask-migrate
(which uses alembic
) then writes out the values in the migration plan: sa.Column('gender', sa.Enum('DOG', 'CAT', 'HAMSTER'))
. It does this for the reason stated above.
If you really want to this, for example because you know the values will never change, you can use sa.Enum(*Animal._member_names_)
, since Animal._member_names_ = ['DOG', 'CAT', 'HAMSTER']
.
回答2:
Couldn't find much information on how to fix this error but here is what you need to do.
after you autogenerated the migration just add create_type=False, to the enum field in the migration file.
sa.Column('user_type', sa.Enum(< ???????? >, create_type=False), nullable=False),
来源:https://stackoverflow.com/questions/63461381/how-to-use-an-existing-sqlalchemy-enum-in-an-alembic-migration-postgres