sqlalchemy ORM查询对象根据上下文返回不同类型的结果

时间:2019-06-24 13:19:11

标签: python-3.x postgresql sqlalchemy

我正在使用炼金术ORM的Query对象。 在不同的上下文中,它返回不同的类型。

我在postgres中有下表:

select * from test;
 test_id | test_col1 | test_col2 
---------+-----------+-----------
       1 | ABC       | ABC
       2 | XYZ       | XYZ

我在Python3中有以下课程:

class Test (DeclarativeBase):
    __tablename__ = 'test'

    id = sa.Column('test_id', sa.Integer(), primary_key=True)
    col1 = sa.Column('test_col1', sa.String(250), nullable = True)
    col2 = sa.Column('test_col2', sa.String(250), nullable = True)

我的查询和结果:

In [2]: q1 = session.query(Test)                                                                                                                                                                                                                                                         

In [3]: rows1 = q1.all()                                                                                                                                                                                                                                                                 

In [4]: print(type(rows1[0]))                                                                                                                                                                                                                                                            
<class '__main__.Test'>

In [5]:                                                                                                                                                                                                                                                                                  

In [5]: cte = session.query(Test).cte()                                                                                                                                                                                                                                                  

In [6]: q2 = session.query(cte)                                                                                                                                                                                                                                                          

In [7]: rows2 = q2.all()                                                                                                                                                                                                                                                                 

In [8]: print(type(rows2[0]))                                                                                                                                                                                                                                                            
<class 'sqlalchemy.util._collections.result'>

In [9]:                                                                                                                                                                                                                                                                                  

In [9]: q3 = session.query(Test).filter(Test.col1 == 'ABC')                                                                                                                                                                                                                              

In [10]: rows3 = q3.all()                                                                                                                                                                                                                                                                

In [11]: print(type(rows3[0]))                                                                                                                                                                                                                                                           
<class '__main__.Test'>

In [12]:                                                                                                                                                                                                                                                                                 

In [12]:                                                                                                                                                                                                                                                                                 

In [12]: q4 = session.query(Test).filter(Test.col1 == 'ABC').one()                                                                                                                                                                                                                       

In [13]: print(type(q4))                                                                                                                                                                                                                                                                 
<class '__main__.Test'>

In [14]:                                                                                                                                                                                                                                                                                 

In [14]: result = session.execute(session.query(Test).filter(Test.col1 == 'ABC'))                                                                                                                                                                                                        

In [15]: for row in result: 
    ...:         print (type(row)) 
    ...:                                                                                                                                                                                                                                                                                 
<class 'sqlalchemy.engine.result.RowProxy'>

仅类型“ sqlalchemy.util._collections.result”允许在行上使用方法_asdict()。 因此,如果我在代码中调用_asdict(),则必须显式检查类型,否则-我会收到“ AttributeError”异常。

是否可以仅从炼金术ORM查询中返回一种类型并使用_asdict()而不进行其他检查?

1 个答案:

答案 0 :(得分:4)

第一个示例:

session.query(Test)
# <__main__.Test>

正在使用声明性orm的查询构建器。当您处于它可以处理的范围之内时,它最有可能做您想做的事,例如返回映射类的实例。

第二个例子

cte = session.query(Test).cte()                                                                                                                                                                                                                                                  
session.query(cte)
# <class 'sqlalchemy.util._collections.result'>

转换为sql

with foo(
    select * from test
)
select * from foo

由于cte可以包含任意sql,因此该间接操作会破坏数据库,并且sqlalchemy对footest之间的关系有所了解。 SQLAlchemy有可能通过显式检查是否要从单个表中选择所有字段来解决此问题,但这尚未实现。而是返回一个通用类型,可以处理任何形状的数据。

第三种情况直接使用较低级别的API session.execute。这是为了从文本执行SQL。它将“智能” ORM查询编译为一个“哑” SQL字符串,该字符串不知道您的python类型是什么,并且再次通过该较低级别的API返回通用类型。

作者_asdict()中的下划线前缀表明该方法是私有方法。这意味着他们可能会随时更改它而不会另行通知,因此您将避免使用它。

您可以按照in the docs

向自己的声明性基类添加.to_dict()方法。

Here's a reference了解如何实现

或者,如果您只是在玩耍,可以随时致电.__dict__()