如何使用SQLAlchemy支持旧模式版本?

如何使用SQLAlchemy支持旧模式版本?,sqlalchemy,alembic,Sqlalchemy,Alembic,我的应用程序处理的是大量的数据库内容,我们不能总是迁移到我们在软件升级时设计的最新数据库模式版本。是的,我们正在使用数据库迁移工具(Alembic),但这还不允许我们拥有能够处理多个模式版本的Python应用程序代码。在接受系统停机的某个时间点,将执行到最新版本的迁移,但同时要求应用程序代码能够处理两个(多个)版本 因此,例如,只有在数据库迁移已经执行的情况下,我们才能提供功能X。如果还没有执行迁移,但是没有提供带有日志中打印的警告的功能X,那么它也应该能够正常工作。我在SQLAlchemy中看

我的应用程序处理的是大量的数据库内容,我们不能总是迁移到我们在软件升级时设计的最新数据库模式版本。是的,我们正在使用数据库迁移工具(Alembic),但这还不允许我们拥有能够处理多个模式版本的Python应用程序代码。在接受系统停机的某个时间点,将执行到最新版本的迁移,但同时要求应用程序代码能够处理两个(多个)版本

因此,例如,只有在数据库迁移已经执行的情况下,我们才能提供功能X。如果还没有执行迁移,但是没有提供带有日志中打印的警告的功能X,那么它也应该能够正常工作。我在SQLAlchemy中看到了几种方法,但它们都让人觉得很难看。我想得到一些关于如何正确处理这件事的建议

例如:

Base = declarative_base()

class MyTable(Base):
    __tablename__ = 'my_table'

    id = Column(MyCustomType, nullable=False, primary_key=True)
    column_a = Column(Integer, nullable=True)
    column_b = Column(String(32))      # old schema
    column_b_new = Column(String(64))  # new schema
新架构版本有一个新列替换旧列。请注意,列名和列数据规范都会更改

另一个要求是,从代码的其他部分使用此类必须是透明的,以支持向后兼容性。该产品的其他组件稍后将了解新的列/数据类型。这意味着,如果使用新模式初始化,旧属性仍然必须是功能性的。因此,如果使用
Mytable(column_a=123,column_b=“abc”)
创建了一个新对象,那么它应该同时使用新模式和旧模式

从这里出发的最佳方式是什么?我看到支持两种模式的选项:

  • 为两个模式版本定义两个MyTable类,然后确定模式版本(如何?),并根据结果使用任一版本。使用这种方法,我认为这需要在使用MyTable类的每个地方使用模式的逻辑,因此很容易中断。将类属性相互链接(
    column\u b=column\u b\u new
    )以实现向后兼容性(这是否确实有效?)
  • 正常初始化数据库,并根据检测到的架构版本更改MyTable类对象。我不确定SQLAlchemy是否支持在初始化后更改声明性基类的属性(列)
  • 创建一个自定义映射器配置,如下所述:我不确定如何从这个SQLAlchemy特性获得我想要的解决方案。也许可以在自定义映射器函数中动态检查自定义属性集

  • 对于初始化,您可以根据检测到的版本动态创建声明性类。为了透明的向后兼容性,您可以尝试使用由多个(旧的和新的)列支持的混合属性。对于初始化,您可以根据检测到的版本动态创建声明性类。为了透明的向后兼容性,您可以尝试使用由多个(旧的和新的)列支持的混合属性。