[英]How to use an existing sqlalchemy Enum in an Alembic migration (Postgres)
在過去的某個時候,我運行了一個 alembic 遷移,它創建了一個users
表,比如......
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),
...
)
...
...它會自動創建名為usertype
的枚舉,其值為"Foo", "Bar", "Baz"
。
現在,我想制作一些其他表,它也引用了相同的枚舉。 例如,
def upgrade():
...
op.create_table('foobar',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
...
sa.Column('user_type', sa.Enum(< ???????? >), nullable=False),
...
)
引用現有枚舉的語法是什么?
我似乎無法在文檔中找到答案: https://docs.sqlalchemy.org/en/13/core/type_basics.html#sqlalchemy.types.Enum
Postgres 有兩個部分可以實現這一點。
create_type=False
sqlalchemy.dialects.postgresql.Enum
(不是sqlalchemy.Enum
)例如:
from sqlalchemy.dialects import postgresql
sa.Column('type', postgresql.ENUM('a', 'b', name='my_enum', create_type=False))
我建議不要這樣做,因為 model 定義和遷移文件之間存在差異。 請記住,如果枚舉發生了變化,那么 Alembic 需要首先檢測枚舉是否發生了變化,其次,知道舊值是什么。 否則,處理它的唯一可能方法是將列類型更改為VARCHAR
之類的類型,然后返回ENUM
,但與僅添加或刪除一個潛在值相比,這是一項更加昂貴和痛苦的操作。
假設我們有以下枚舉:
class Animal(enum.Enum):
DOG = 'DOG'
CAT = 'CAT'
HAMSTER = 'HAMSTER'
對於postgres
,您可以使用sqlalchemy.dialects.postgres.ENUM
並將其傳遞給現有的枚舉:
animal = Column(ENUM(Animal), nullable=False)
但是flask-migrate
(使用alembic
)然后寫出遷移計划中的值: sa.Column('gender', sa.Enum('DOG', 'CAT', 'HAMSTER'))
。 它這樣做是出於上述原因。
如果你真的想要這樣做,例如因為你知道值永遠不會改變,你可以使用sa.Enum(*Animal._member_names_)
,因為Animal._member_names_ = ['DOG', 'CAT', 'HAMSTER']
。
找不到有關如何修復此錯誤的太多信息,但這是您需要做的。
自動生成遷移后,只需將 create_type=False, 添加到遷移文件中的枚舉字段。
sa.Column('user_type', sa.Enum(< ???????? >, create_type=False), nullable=False),
您可能需要傳遞枚舉 object 而不是其名稱作為字符串。
entity = Column(
postgresql.ENUM(
SocialType,
create_type=False,
checkfirst=True,
inherit_schema=True,
)
)
checkfirst=True
和create_type=False
不會被 alembic 檢測到。 所以需要手動添加。 最后,alembic 遷移應該看起來像
sa.Column('entity', postgresql.ENUM('github', 'twitter', name='socialtype', schema='dashboard', inherit_schema=True, create_type=False, checkfirst=True), nullable=True),
有關此問題的簡單、有效且與后端無關的解決方案,請在另一個線程中查看我的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.