模型FacebookPost和TwitterPost共享一个名为类型的枚举。在创建facebook_posts表时正确创建此枚举,但在尝试创建twitter_posts表时,尝试重新创建此类型会导致错误。
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) type "types" already exists
[SQL: "CREATE TYPE types AS ENUM ('Video', 'GIF', 'Scratch Reel', 'Card', 'Video Card', 'Text', 'Photo', 'Shared Article', 'Reply', 'Canvas', 'Carousel', 'Video Carousel', 'Link', 'Status')"]
这就是我创建数据库的方式。我无法使用Base.metadata.create_all,因为我需要明确表示创建的表
Engine = create_engine(db_url, echo=False)
Campaign.__table__.create(Engine)
SubCampaign.__table__.create(Engine)
Creative.__table__.create(Engine)
Hashtag.__table__.create(Engine)
FacebookPost.__table__.create(Engine)
TwitterPost.__table__.create(Engine)
我以这种方式创建枚举:
from sqlalchemy import Enum
types = ('Video', 'GIF', 'Scratch Reel', 'Card', 'Video Card',
'Text', 'Photo', 'Shared Article', 'Reply', 'Canvas',
'Carousel', 'Video Carousel', 'Link', 'Status')
goals = ('CTR', 'ER', 'Awareness', 'CPGA')
sources = ('Facebook', 'Twitter', 'Instagram', 'Tumblr')
vars_ = locals().copy()
for k, v in vars_.items():
if isinstance(v, tuple):
locals()[k] = Enum(*v, name=k)
答案 0 :(得分:1)
通用Enum类不提供对发出CREATE TYPE
语句的任何控制。但是PostgreSQL特定的替代方法ENUM
具有参数create_type
,可用于禁用它:
from sqlalchemy.dialects.postgresql import ENUM
class TwitterPost(Base):
...
type = Column("type", ENUM(*types, name="post_type", create_type=False))
...
答案 1 :(得分:1)
我在Alembic中遇到了类似的问题,并使用了解决方法。
第一个示例不起作用。 SQLAlchemy在调用create
时创建枚举,但是在创建表时尝试再次创建该枚举,从而导致错误。
NEW_ENUM = sa.Enum(
"A",
"B",
"C",
name="my_enum",
schema="my_schema"
)
NEW_ENUM.create(op.get_bind())
op.create_table(
"table1",
sa.MetaData(),
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("column1", sa.String),
sa.Column("column2", NEW_ENUM),
schema="my_schema",
)
op.create_table(
"table2",
sa.MetaData(),
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("column1", sa.Integer),
sa.Column("column2", NEW_ENUM),
schema="my_schema",
)
但是,创建没有枚举列的表并在之后添加它们是可行的。枚举在数据库上创建一次(在我的情况下为Postgres),并用于添加列中的两个表:
NEW_ENUM = sa.Enum(
"A",
"B",
"C",
name="my_enum",
schema="my_schema"
)
NEW_ENUM.create(op.get_bind())
op.create_table(
"table1",
sa.MetaData(),
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("column1", sa.String),
schema="my_schema",
)
op.add_column("table1", sa.Column("column2", NEW_ENUM), schema="my_schema")
op.create_table(
"table2",
sa.MetaData(),
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("column1", sa.Integer),
schema="my_schema",
)
op.add_column("table2", sa.Column("column2", NEW_ENUM), schema="my_schema")
答案 2 :(得分:0)
对于使用 Alembic 并遇到此问题的任何人。
还有一个 postgresql.ENUM
kwarg 表示 sa.Column('ActionType', postgresql.ENUM('Primary', 'Secondary', name='actiontype', create_type=False), nullable=True),
。用于在 alembic 迁移脚本中设置枚举类型列的架构。
这是我的列定义的样子。 (使用现有的枚举)
SQLAlchemy==1.1.1
现在将使用现有枚举作为新列,而不创建新列。
我在我的需求文件中使用了 alembic==0.8.8
和 movePlayer(Vector3 direction)
。
我给出了类似的答案here。