我正在使用炼金术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()而不进行其他检查?
答案 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对foo
和test
之间的关系有所了解。 SQLAlchemy有可能通过显式检查是否要从单个表中选择所有字段来解决此问题,但这尚未实现。而是返回一个通用类型,可以处理任何形状的数据。
第三种情况直接使用较低级别的API session.execute
。这是为了从文本执行SQL。它将“智能” ORM查询编译为一个“哑” SQL字符串,该字符串不知道您的python类型是什么,并且再次通过该较低级别的API返回通用类型。
作者_asdict()
中的下划线前缀表明该方法是私有方法。这意味着他们可能会随时更改它而不会另行通知,因此您将避免使用它。
您可以按照in the docs
向自己的声明性基类添加.to_dict()
方法。
Here's a reference了解如何实现
或者,如果您只是在玩耍,可以随时致电.__dict__()