sqlalchemy 中特定于方言的表名和列名,同时重用现有的 ORM 映射

问题描述

我使用 sqlalchemy 的 ORM 库与我们应用程序的数据库之一进行交互。在一台主机上,应用实例的数据库后端是 Postgresql,而在另一台主机上,由于历史原因,我们使用 MysqL

两个后端的模式(和关系)是相同的,但是 Postgresql 中的表和列名称是小写的,而在 MysqL 中它们是大写的。有什么方法可以在 sqlalchemy 中调整我的架构,这样我就不需要重复代码吗?

以下是我的架构示例。提示,该应用程序是 Confluence wiki ;)

from sqlalchemy import (
    BigInteger,Column,DateTime,String,)
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Space(Base):
    __tablename__ = 'spaces'

    spaceid = Column(BigInteger,primary_key=True)
    spacename = Column(String(255))
    spacekey = Column(String(255),nullable=False,unique=True)
    lowerspacekey = Column(String(255),index=True)
    spacedescid = Column(BigInteger,index=True)
    homepage = Column(BigInteger,index=True)
    creator = Column(String(255),index=True)
    creationdate = Column(DateTime,index=True)
    lastmodifier = Column(String(255),index=True)
    lastmoddate = Column(DateTime)
    spacetype = Column(String(255))
    spacestatus = Column(String(255),index=True)

解决方法

感谢@rfkortekaas 的建议,我设法通过自动映射架构并随后覆盖表名和列名的命名方案来解决该问题。

sqlalchemy 的文档有两个非常有用的页面:

为了后代:

from sqlalchemy import event
from sqlalchemy.ext.automap import automap_base
from .utilities import to_pascal_case,to_snake_case


AutomapBase = automap_base()


@event.listens_for(AutomapBase.metadata,"column_reflect")
def column_reflect(inspector,table,column_info):
    column_info['key'] = to_snake_case(column_info['name'])


def classname_for_table(base,table_name,table):
    return to_pascal_case(table_name)


if __name__ == '__main__':
    dbcs = 'postgresql://username:password@127.0.0.1:3306/database'
    automap_engine = create_engine(dbcs,future=True,echo=verbose > 2)
    AutomapBase.prepare(
        autoload_with=automap_engine,classname_for_table=classname_for_table,)

    # Access the automapped classes with AutomapBase.classes.<class_name>