如何将Sqlalchemy ORM查询结果转换为包含关系的单个联接表?

时间:2019-07-08 18:52:29

标签: python sqlalchemy

我正在为Web应用程序数据库使用现有的Python API,希望为用户提供查询结果的格式选项。在某些情况下,JSON适用,而在其他情况下则为CSV。该API围绕SQLAlchemy声明性ORM构建,并且系统中的查询通常返回ORM实例或实例列表及其关系。将此转换为JSON很简单,但是我在检索类似表格的视图以将结果转换为CSV时遇到麻烦。使用SQLAlchemy核心操作或简单的SQL,很容易取回联接的表视图。我知道在幕后,SQLAlchemy正在构造必要的SQL语句并加入以执行我要的操作,但是它隐藏在映射器的后面。

鉴于我正在使用的API已经设置为使用ORM类以声明方式查询所有内容,那么在SQLAlchemy执行其将所有内容都映射回对象的魔术之前,如何获取数据库返回的行?< / p>

user_addresses = Table("user_addresses", Base.metadata,
    Column("user_id", Integer, ForeignKey("user.id")),
    Column("address_id", Integer, ForeignKey("address.id"))
)

class User(Base):
    __tablename__ = "user"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String)
    addresses = relationship("Address", secondary=user_addresses, back_populates="users")


class Address(Base):
    __tablename__ = "address"
    id = Column(Integer, primary_key=True, autoincrement=True)
    number = Column(Integer)
    street = Column(String)
    city = Column(String)
    state = Column(String)
    zip = Column(Integer)
    users = relationship("User", secondary=user_addresses, back_populates="addresses")


## configure session, engine, etc.
# get all relationships loaded together
statement = session.query(User).options(joinedload("*"))
# normal orm classes
results = statement.all()
# I want something like
flat_results = statement.table()

我认为类似以上的内容必须直接与预先映射的表进行交互,但是我不确定如何在不重写后端查询API的情况下返回表。

1 个答案:

答案 0 :(得分:1)

为我自己的问题提供可能的答案,因此,如果您有更好的选择,请随时进行答复。

到目前为止,我发现最简单的方法是提取将由Session执行的实际SQL语句,然后直接使用execute方法执行该语句:

statement = session.query(User).options(joinedload("*"))
results = session.execute(str(statement))
colnames = results.keys()
rows = results.fetchall()

这样,您可以利用SQLAlchemy的所有自动细木工技术,仍然可以获取数据的完整表视图。

修改: 正如@IljaEverilä指出的那样,最好调用Query.statement以获取具有所有正确参数替换和特定于后端的功能的最终SQL命令:

statement = session.query(User).options(joinedload("*")).statement
results = session.execute(statement)
colnames = results.keys()
rows = results.fetchall()