-->

Merge multiple declarative bases in SQLAlchemy

2020-06-03 00:35发布

问题:

Is it possible to merge a _BoundDeclarativeMeta instance with another?

For example:

from sqlalchemy.ext.declarative import declarative_base

Base1 = declarative_base()
Base2 = declarative_base()

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

In reality I would be subclassing orm models from each of them before merging. The problem is that I have an independent package that needs certain tables to work. Yet it is going to be used by another independent package.

回答1:

For my use case this worked:

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)

Or, even better, automatically merge all declarative bases:

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)

That meta data can then be used for example to create a diff to the current database:

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)