【问题标题】:Merge multiple declarative bases in SQLAlchemy在 SQLAlchemy 中合并多个声明性基础
【发布时间】:2015-07-09 09:26:04
【问题描述】:

是否可以将 _BoundDeclarativeMeta 实例与另一个实例合并?

例如:

from sqlalchemy.ext.declarative import declarative_base

Base1 = declarative_base()
Base2 = declarative_base()

# Something like this?
CombinedBase = Base1.merge(Base2)

实际上,在合并之前,我会从它们中的每一个中继承 orm 模型。问题是我有一个独立的包,需要某些表才能工作。然而它将被另一个独立的包使用。

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    对于我的用例,这可行:

    from sqlalchemy import MetaData
    
    combined_meta_data = MetaData()
    
    for declarative_base in [Base1, Base2]:
        for (table_name, table) in declarative_base.metadata.tables.items():
            combined_meta_data._add_table(table_name, table.schema, table)
    

    或者,更好的是,自动合并所有声明基:

    import gc
    from sqlalchemy import MetaData
    
    combined_meta_data = MetaData()
    
    for declarative_base in ([obj for obj in gc.get_objects() if isinstance(obj, DeclarativeMeta)]):
        for (table_name, table) in declarative_base.metadata.tables.items():
            combined_meta_data._add_table(table_name, table.schema, table)
    

    然后可以使用该元数据创建与当前数据库的差异:

    from sqlalchemy import create_engine
    from alembic.migration import MigrationContext
    from alembic.autogenerate import compare_metadata
    import pprint
    
    engine = create_engine(...)
    migration_context = MigrationContext.configure(engine.connect())
    
    diff = compare_metadata(migration_context, combined_meta_data)
    pprint.pprint(diff)
    

    【讨论】:

    • 有没有办法只使用稳定的SQ API,而不是_add_table
    【解决方案2】:

    sqlalchemy.Table.to_metadata 似乎是一种非内部 API,可以将表从一个元数据对象复制到另一个元数据对象。

    from sqlalchemy import MetaData
    from sqlalchemy.ext.declarative import declarative_base
        
    def merge_metadata(*original_metadata) -> MetaData:
        merged = MetaData()
    
        for original_metadatum in original_metadata:
            for table in original_metadatum.tables.values():
                table.to_metadata(merged)
        
        return merged
    
    Base1 = declarative_base()
    Base2 = declarative_base()
    print(merge_metadata(Base1.metadata, Base2.metadata).tables)
    

    【讨论】:

    • 这行得通,似乎是 2021 年的最新方法
    猜你喜欢
    • 2014-05-06
    • 2015-02-25
    • 2010-10-22
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2011-03-28
    相关资源
    最近更新 更多