简体   繁体   English

SQLAlchemy将表联合映射到类

[英]SQLAlchemy mapping a table union to a class

I'm using SQLAlchemy to query a number of similar tables, and union the results. 我正在使用SQLAlchemy查询许多类似的表,并将结果联合起来。 The tables are rows of customer information, but our current database structures it so that different groups of customers are in their own tables eg client_group1, client_group2, client_group3: 这些表是客户信息的行,但我们当前的数据库构建它,以便不同的客户组在他们自己的表中,例如client_group1,client_group2,client_group3:

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

Each of the other tables have identical columns. 每个其他表具有相同的列。 If I'm using SQLAlchemy declarative_base, I can have a class for client_group1 like the following: 如果我正在使用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))

Then I can do queries such as: 然后我可以做如下的查询:

session.query(ClientGroup1.name)

However, if I use union_all to combine a bunch of client tables into a viewport, such as: 但是,如果我使用union_all将一堆客户端表组合到视口中,例如:

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

then I'm not sure how to map a viewport to an object, and instead I have to access viewport columns using: 然后我不确定如何将视口映射到对象,而是我必须使用以下方法访问视口列:

viewport.c.name

Is there any way to map the viewport to a specific table structure? 有没有办法将视口映射到特定的表结构? Especially considering the fact that each class points to a different __table_name__ 特别考虑到每个类指向不同的__table_name__的事实

Read Concrete Table Inheritance documentation for the idea how this can be done. 阅读具体表继承文档,了解如何完成此操作。 The code below is a running example of how this can be done: 下面的代码是一个如何完成此操作的运行示例:

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()

The above example has an added benefit that you can also create new objects, as well as query only some tables. 上面的示例还有一个额外的好处,您还可以创建新对象,以及仅查询某些表。

You could do it mapping an SQL VIEW to a class, but you need to specify a primary key explicitly (see Is possible to mapping view with class using mapper in SqlAlchemy? ). 您可以将SQL VIEW映射到一个类,但是您需要显式指定一个主键(请参阅SqlAlchemy中的使用mapper的类映射视图? )。 In you case, I am afraid, this might not work because of the same PK value in multiple tables, and using a multi-column PK might not be the best idea. 在你的情况下,我担心,由于多个表中的PK值相同,这可能不起作用,并且使用多列PK可能不是最好的主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM