[英]How do I change column type on SQLAlchemy declarative model dynamically?
[英]Change SqlAlchemy declarative model table schema at runtime
我正在尝试构建一个在 postgres 和 sqlite 中运行的声明表。 表之间的唯一区别是 postgres 表将在特定模式中运行,而 sqlite 表不会。 到目前为止,我已经使用下面的代码在没有架构的情况下构建了表。
metadata = MetaData()
class Base(object):
__table_args__ = {'schema': None}
Base = declarative_base(cls=Base, metadata=metadata)
class Configuration(Base):
"""
Object representation of a row in the configuration table
"""
__tablename__ = 'configuration'
name = Column(String(90), primary_key=True)
value = Column(String(256))
def __init__(self, name="", value=""):
self.name = name
self.value = value
def build_tables(conn_str, schema=None):
global metadata
engine = create_engine(conn_str, echo=True)
if schema:
metadata.schema=schema
metadata.create_all(engine)
但是,每当我尝试在 build_tables() 中设置架构时,该架构似乎都没有在新建的表中设置。 只有当我最初在metadata = MetaData(schema='my_project')
处设置架构时,它似乎才起作用,在我知道将运行哪个数据库之前我不想这样做。
是否有另一种使用声明性模型动态设置表模式的方法? 更改元数据是错误的方法吗?
尽管这不是您正在寻找的 100% 的答案,但我认为 @Ilja Everilä 是正确的答案部分在https://stackoverflow.com/a/9299021/3727050 中。
我需要做的是将模型“复制”到新的 declarative_base。 结果,我遇到了与您类似的问题:我需要:
__table__
属性以指向新的元数据。 否则我在该表中查找 PK 时会遇到很多错误似乎对我有用的解决方案是通过以下方式克隆模式:
def rebase(klass, new_base):
new_dict = {
k: v
for k, v in klass.__dict__.items()
if not k.startswith("_") or k in {"__tablename__", "__table_args__"}
}
# Associate the new table with the new metadata instead
# of the old/other pool
new_dict["__table__"] = klass.__table__.to_metadata(new_base.metadata)
# Construct and return a new type
return type(klass.__name__, (new_base,), new_dict)
在您的情况下,这可以用作:
...
# Your old base
Base = declarative_base(cls=Base, metadata=metadata)
# New metadata and base
metadata2 = MetaData(schema="<new_schema>")
Base2 = declarative_base(cls=Base, metadata=metadata)
# Register Model/Table in the new base and meta
NewConfiguration = rebase(Configuration, Base2)
metadata2.create_all(engine)
注意/警告:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.