[英]SQLAlchemy. Creating tables that share enum
Models FacebookPost and TwitterPost share an enum called types.模型 FacebookPost 和 TwitterPost 共享一个名为 types 的枚举。 This enum is correctly created when creating facebook_posts table, but when trying to create twitter_posts table, there is an attempt to recreate this type which results in an error.
在创建 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')"]
This is the way I'm creating the database.这就是我创建数据库的方式。 I can't use Base.metadata.create_all, because I need to be explicit in terms of what tables are created
我不能使用 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)
I'm creating the enums this way:我正在以这种方式创建枚举:
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)
The generic Enum class does not offer any control over emitting the CREATE TYPE
statement.泛型Enum类不提供对发出
CREATE TYPE
语句的任何控制。 But a PostgreSQL-specific alternative ENUM
has a parameter create_type
which can be used to disable it:但是特定于 PostgreSQL 的替代
ENUM
有一个参数create_type
可用于禁用它:
from sqlalchemy.dialects.postgresql import ENUM
class TwitterPost(Base):
...
type = Column("type", ENUM(*types, name="post_type", create_type=False))
...
I faced a similar problem in Alembic and used a workaround.我在 Alembic 中遇到了类似的问题并使用了一种解决方法。
The first example doesn't work.第一个例子不起作用。 SQLAlchemy creates the enum when
create
is called on it, but tries to create it again when it creates the tables, causing an error. SQLAlchemy 在调用
create
时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",
)
However, creating the tables without the enum columns and adding them afterwards works.但是,创建没有枚举列的表并随后添加它们是可行的。 The enum is created once on the database (Postgres in my case) and used for the two tables in the added columns:
枚举在数据库上创建一次(在我的例子中是 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")
For anyone using Alembic and having this issue.对于使用 Alembic 并遇到此问题的任何人。
There's also a create_type
kwarg for postgresql.ENUM
. postgresql.ENUM
还有一个create_type
kwarg。 which is used to set the schema for an enum type column in the alembic migration script.它用于在 alembic 迁移脚本中设置枚举类型列的架构。
Here's what my column definition looks like.这是我的列定义的样子。 (Which uses existing an existing enum)
(使用现有的枚举)
sa.Column('ActionType', postgresql.ENUM('Primary', 'Secondary', name='actiontype', create_type=False), nullable=True),
This will now use the existing enum for the new column without creating a new one.这现在将使用现有的枚举作为新列而不创建新列。
I'm using SQLAlchemy==1.1.1
and alembic==0.8.8
in my requirements file.我在我的需求文件中使用
SQLAlchemy==1.1.1
和alembic==0.8.8
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.