SQLAlchemy execute() return ResultProxy as Tuple, not dict
我有以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | query =""" SELECT Coalesce((SELECT sp.param_value FROM sites_params sp WHERE sp.param_name = 'ci' AND sp.site_id = s.id ORDER BY sp.id DESC LIMIT 1), -1) AS ci FROM sites s WHERE s.deleted = 0 AND s.id = 10 """ site = db_session.execute(query) # print site # <sqlalchemy.engine.result.ResultProxy object at 0x033E63D0> site = db_session.execute(query).fetchone() print site # (u'375') print list(site) # [u'375'] |
为什么SQLAlchemy对于此查询返回元组而不是字典? 我想使用以下样式来访问查询结果:
1 2 | print site.ci # u'375' |
您是否看过ResultProxy文档?
它准确地描述了@Gryphius和@Syed Habib M的建议,即使用
从文档:
Individual columns may be accessed by their integer position,
case-insensitive column name, or by schema.Column object. e.g.:row = fetchone()
col1 = row[0] # access via integer position
col2 = row['col2'] # access via name
col3 = row[mytable.c.mycol] # access via Column object.
这是一个老问题,但今天仍然有意义。使SQL Alchemy返回字典非常有用,尤其是在使用基于RESTful的返回JSON的API时。
这是我在Python 3中使用
1 2 3 4 5 6 7 8 9 | resultproxy = db_session.execute(query) d, a = {}, [] for rowproxy in resultproxy: # rowproxy.items() returns an array like [(key0, value0), (key1, value1)] for column, value in rowproxy.items(): # build up the dictionary d = {**d, **{column: value}} a.append(d) |
最终结果是,数组
至于如何在SQL Alchemy中工作:
-
db_session.execute(query) 返回一个ResultProxy 对象 -
ResultProxy 对象由RowProxy 对象组成 -
RowProxy 对象具有.items() 方法,该方法返回键,该行中所有项目的值元组,可以在for 操作中将它们解压缩为key, value 。
这里是一种单线替代:
1 | [{column: value for column, value in rowproxy.items()} for rowproxy in resultproxy] |
从文档:
class sqlalchemy.engine.RowProxy(parent, row, processors, keymap)
Proxy values from a single cursor row.
Mostly follows"ordered dictionary" behavior, mapping result values to the string-based column name, the integer position of the result in the row, as well as Column instances which can be mapped to the original Columns that produced this result set (for results that correspond to constructed SQL expressions).
has_key(key)
Return True if this RowProxy contains the given key.items()
Return a list of tuples, each tuple containing a key/value pair.keys()
Return the list of keys as strings represented by this RowProxy.
链接:http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items
我建立了一个简单的类,使其在我们的流程中像数据库界面一样工作。它去了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from sqlalchemy import create_engine class DBConnection: def __init__(self, db_instance): self.db_engine = create_engine('your_database_uri_string') self.db_engine.connect() def read(self, statement): """Executes a read query and returns a list of dicts, whose keys are column names.""" data = self.db_engine.execute(statement).fetchall() results = [] if len(data)==0: return results # results from sqlalchemy are returned as a list of tuples; this procedure converts it into a list of dicts for row_number, row in enumerate(data): results.append({}) for column_number, value in enumerate(row): results[row_number][row.keys()[column_number]] = value return results |
这可能有助于解决OP问题。我认为他遇到的问题是,行对象仅包含列值,而不包含列名本身,这与ORM查询的情况相同,在ORM查询中,结果具有包含键和值的dict属性。
python sqlalchemy动态获取列名?
您可以使用
如果
为了拥有
1 2 3 | from collections import namedtuple Site = namedtuple('Site', site.keys()) record = Site(*site) |
我更喜欢用列表理解来创建一个帮助器类和方法:
1 2 3 4 5 6 | class ResultHelper(): @classmethod def resultproxy_to_dict_list(cls, sql_alchemy_rowset): return [{tuple[0]: tuple[1] for tuple in rowproxy.items()} for rowproxy in sql_alchemy_rowset] |