gpt4 book ai didi

python - 如何将枚举与 SQLAlchemy 和 Alembic 一起使用?

转载 作者:太空狗 更新时间:2023-10-30 01:11:50 24 4
gpt4 key购买 nike

这是我的 Post 模型:

class Post(Base):
__tablename__ = 'posts'

title = db.Column(db.String(120), nullable=False)
description = db.Column(db.String(2048), nullable=False)

我想给它添加 Enum status。所以,我创建了一个新的枚举:

import enum

class PostStatus(enum.Enum):
DRAFT='draft'
APPROVE='approve'
PUBLISHED='published'

并为模型添加了一个新字段:

class Post(Base):
...
status = db.Column(db.Enum(PostStatus), nullable=False, default=PostStatus.DRAFT.value, server_default=PostStatus.DRAFT.value)

完成FLASK_APP=server.py flask db migrate后,生成了这样的迁移:

def upgrade():
op.add_column('posts', sa.Column('status', sa.Enum('DRAFT', 'APPROVE', 'PUBLISHED', name='poststatus'), server_default='draft', nullable=False))

尝试升级数据库后,我得到:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) type "poststatus" does not exist
LINE 1: ALTER TABLE posts ADD COLUMN status poststatus DEFAULT 'draf...
^
[SQL: "ALTER TABLE posts ADD COLUMN status poststatus DEFAULT 'draft' NOT NULL"]
  1. 为什么类型 poststatus 没有在数据库级自动创建?在类似的迁移中。
  2. 如何正确指定server_default 选项?我需要 ORM 级默认值和 DB 级默认值,因为我正在更改现有行,因此不应用 ORM 默认值。
  3. 为什么 DB 中的实际值是“DRAFT”、“APPROVE”、“PUBLISHED”,而不是 draft 等?我认为应该有 ENUM 值,而不是名称。

提前谢谢你。

最佳答案

Why real values in DB are 'DRAFT', 'APPROVE', 'PUBLISHED', but not draft, etc? I supposed there should be ENUM values, not names.

正如 Peter Bašista 已经提到的,SQLAlchemy 在数据库中使用枚举名称(DRAFT、APPROVE、PUBLISHED)。我认为这样做是因为枚举值(“草稿”、“批准”、...)在 Python 中可以是任意类型,并且不能保证它们是唯一的(除非使用 @unique) .

然而,自从 SQLAlchemy 1.2.3 以来,Enum 类接受一个参数 values_callable,它可用于存储枚举值 在数据库中:

    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.

我认为基本上您遇到了 alembic 的限制:在某些情况下它无法正确处理 PostgreSQL 上的枚举。我怀疑您案例中的主要问题是 Autogenerate doesn't correctly handle postgresql enums #278 .

我注意到如果我使用 alembic.op.create_table 类型创建正确所以我的解决方法基本上是:

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)

关于python - 如何将枚举与 SQLAlchemy 和 Alembic 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47206201/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com