【问题标题】:SQLAlchemy mapping a table union to a classSQLAlchemy 将表联合映射到类
【发布时间】:2015-03-24 05:25:10
【问题描述】:

我正在使用 SQLAlchemy 查询许多类似的表,并将结果合并。这些表是客户信息的行,但是我们当前的数据库对其进行了结构化,以便不同的客户组在他们自己的表中,例如客户端组1、客户端组2、客户端组3:

client_group1:
| id |     name    |        email        |
| 1  |  john       | johnsmith@gmail.com |
| 2  |  greg       | gregjones@gmail.com |

其他每个表都有相同的列。如果我使用的是 SQLAlchemy declarative_base,我可以为 client_group1 提供一个类,如下所示:

def ClientGroup1(Base):
    __tablename__ = 'client_group1'
    __table_args__ = {u'schema': 'clients'}

    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    email = Column(String(32))

然后我可以进行如下查询:

session.query(ClientGroup1.name)

但是,如果我使用 union_all 将一堆客户端表合并到一个视口中,例如:

query1 = session.query(ClientGroup1.name)
query2 = session.query(ClientGroup2.name)
viewport = union_all(query1, query2)

然后我不确定如何将视口映射到对象,而是必须使用以下方法访问视口列:

viewport.c.name

有没有办法将视口映射到特定的表结构?特别是考虑到每个类指向不同的__table_name__这一事实

【问题讨论】:

  • 您是只读取/查询数据还是创建/更新数据?
  • 只是读取/查询,没有计划使用该表来创建/更新目的。

标签: python sqlalchemy


【解决方案1】:

阅读Concrete Table Inheritance 文档以了解如何做到这一点。下面的代码是如何做到这一点的运行示例:

from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.orm import sessionmaker, configure_mappers
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.declarative import AbstractConcreteBase

engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base(engine)


class ClientGroupBase(AbstractConcreteBase, Base):
    pass


class ClientGroup1(ClientGroupBase):
    __tablename__ = 'client_group1'
    # __table_args__ = {'schema': 'clients'}
    __mapper_args__ = {
        'polymorphic_identity': 'client_group1',
        'concrete': True,
    }

    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    email = Column(String(32))


class ClientGroup2(ClientGroupBase):
    __tablename__ = 'client_group2'
    # __table_args__ = {'schema': 'clients'}
    __mapper_args__ = {
        'polymorphic_identity': 'client_group2',
        'concrete': True,
    }

    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    email = Column(String(32))


def _test_model():
    # generate classes for all tables
    Base.metadata.create_all()
    print('-'*80)

    # configure mappers (see documentation)
    configure_mappers()
    print('-'*80)

    # add some test data
    session.add(ClientGroup1(name="name1"))
    session.add(ClientGroup1(name="name1"))
    session.add(ClientGroup2(name="name1"))
    session.add(ClientGroup2(name="name1"))
    session.commit()
    print('-'*80)

    # perform a query
    q = session.query(ClientGroupBase).all()
    for r in q:
        print(r)


if __name__ == '__main__':
    _test_model()

上面的示例还有一个额外的好处,即您还可以创建新对象,以及只查询一些表。

您可以将SQL VIEW 映射到一个类,但您需要明确指定一个主键(请参阅Is possible to mapping view with class using mapper in SqlAlchemy?)。在您的情况下,恐怕这可能不起作用,因为多个表中的 PK 值相同,并且使用多列 PK 可能不是最好的主意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-12
    • 2013-07-03
    • 2013-08-01
    • 1970-01-01
    • 2021-01-26
    • 2019-04-06
    • 2019-01-05
    • 2021-12-09
    相关资源
    最近更新 更多