Fra*_*tia 6 python postgresql enums sqlalchemy
模型 FacebookPost 和 TwitterPost 共享一个名为 types 的枚举。在创建 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')"]
Run Code Online (Sandbox Code Playgroud)
这就是我创建数据库的方式。我不能使用 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)
Run Code Online (Sandbox Code Playgroud)
我正在以这种方式创建枚举:
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)
Run Code Online (Sandbox Code Playgroud)
Pet*_*sta 15
通用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))
...
Run Code Online (Sandbox Code Playgroud)
小智 8
我在 Alembic 中遇到了类似的问题并使用了解决方法。
第一个例子不起作用。create
SQLAlchemy 在调用时会创建枚举,但在创建表时会尝试再次创建它,从而导致错误。
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",
)
Run Code Online (Sandbox Code Playgroud)
但是,创建不带枚举列的表并随后添加它们是可行的。枚举在数据库(在我的例子中是 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")
Run Code Online (Sandbox Code Playgroud)
对于任何使用 Alembic 并遇到此问题的人。
还有一个create_type
kwarg postgresql.ENUM
。它用于在 alembic 迁移脚本中设置枚举类型列的架构。
这是我的列定义的样子。(它使用现有的现有枚举)
sa.Column('ActionType', postgresql.ENUM('Primary', 'Secondary', name='actiontype', create_type=False), nullable=True),
Run Code Online (Sandbox Code Playgroud)
现在,这将使用现有的枚举作为新列,而不创建新的枚举。
我正在我的需求文件中使用SQLAlchemy==1.1.1
and 。alembic==0.8.8
我在这里给出了类似的答案。