SQLAlchemy 将 table 联合映射到 class
SQLAlchemy mapping a table union to a class
我正在使用 SQLAlchemy 查询许多类似的 table,然后合并结果。 tables 是客户信息行,但我们当前的数据库对其进行结构化,以便不同的客户组在他们自己的 tables 中,例如client_group1, client_group2, client_group3:
client_group1:
| id | name | email |
| 1 | john | johnsmith@gmail.com |
| 2 | greg | gregjones@gmail.com |
其他每个 table 都有相同的列。如果我使用 SQLAlchemy declarative_base,我可以为 client_group1 设置一个 class,如下所示:
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将一堆客户端table组合成一个视口,例如:
query1 = session.query(ClientGroup1.name)
query2 = session.query(ClientGroup2.name)
viewport = union_all(query1, query2)
然后我不确定如何将视口映射到对象,而是我必须使用以下方法访问视口列:
viewport.c.name
有没有办法将视口映射到特定的 table 结构?特别是考虑到每个 class 指向不同的 __table_name__
阅读 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
映射到 class,但您需要明确指定主键(请参阅 Is possible to mapping view with class using mapper in SqlAlchemy?)。在你的情况下,恐怕这可能行不通,因为多个表中的 PK 值相同,使用多列 PK 可能不是最好的主意。
我正在使用 SQLAlchemy 查询许多类似的 table,然后合并结果。 tables 是客户信息行,但我们当前的数据库对其进行结构化,以便不同的客户组在他们自己的 tables 中,例如client_group1, client_group2, client_group3:
client_group1:
| id | name | email |
| 1 | john | johnsmith@gmail.com |
| 2 | greg | gregjones@gmail.com |
其他每个 table 都有相同的列。如果我使用 SQLAlchemy declarative_base,我可以为 client_group1 设置一个 class,如下所示:
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将一堆客户端table组合成一个视口,例如:
query1 = session.query(ClientGroup1.name)
query2 = session.query(ClientGroup2.name)
viewport = union_all(query1, query2)
然后我不确定如何将视口映射到对象,而是我必须使用以下方法访问视口列:
viewport.c.name
有没有办法将视口映射到特定的 table 结构?特别是考虑到每个 class 指向不同的 __table_name__
阅读 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
映射到 class,但您需要明确指定主键(请参阅 Is possible to mapping view with class using mapper in SqlAlchemy?)。在你的情况下,恐怕这可能行不通,因为多个表中的 PK 值相同,使用多列 PK 可能不是最好的主意。