SQLAlchemy execute()将ResultProxy作为Tuple返回,而不是dict

时间:2013-12-23 12:39:49

标签: python sqlalchemy

我有以下代码:

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会为此查询返回元组而不是dicts?我想使用以下样式来访问查询结果:

print site.ci
# u'375'

8 个答案:

答案 0 :(得分:13)

您是否看过ResultProxy文档? 它准确描述了@Gryphius和@Syed Habib M所建议的内容,即使用site['ci']

ResultProxy没有像您声明的那样“返回一个元组” - 它(不奇怪)是一个像元组一样行为(例如打印)的代理,但也支持字典式访问:

来自文档:

  

可以按整数位置访问各列,   不区分大小写的列名,或schema.Column对象。 e.g:

     

row = fetchone()

     

col1 = row [0]#通过整数位置访问

     

col2 = row ['col2']#通过名称访问

     

col3 = row [mytable.c.mycol]#通过Column对象访问。

答案 1 :(得分:8)

这是一个老问题,但今天仍然有用。让SQL Alchemy返回字典非常有用,尤其是在使用返回JSON的基于RESTful的API时。

以下是我使用Python 3中的db_session进行的操作:

site = 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)

最终结果是数组a现在以字典格式包含您的查询结果。

至于它如何在SQL Alchemy中工作:

  • db_session.execute(query)会返回ResultProxy个对象
  • ResultProxy对象由RowProxy个对象
  • 组成
  • RowProxy对象有一个.items()方法,它返回行中所有项的键值元组,可以在key, value操作中解压缩为for

这里有一个单线替代方案:

[{column: value for column, value in rowproxy.items()} for rowproxy in resultproxy]

来自文档:

  

class sqlalchemy.engine.RowProxy(parent,row,processors,keymap)

     

单个游标行的代理值。

     

主要遵循“有序字典”行为,将结果值映射到基于字符串的列名,行中结果的整数位置,以及可以映射到生成此结果集的原始列的列实例(对应于构造的SQL表达式的结果)。

     

对象的has_key(key)的   如果此RowProxy包含给定键,则返回True。

     

项()   返回一个元组列表,每个元组包含一个键/值对。

     

键()   将键列表作为此RowProxy表示的字符串返回。

链接:http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items

答案 2 :(得分:3)

这可能有助于解决OP问题。我认为他遇到的问题是行对象只包含列值,而不是列名称本身,就像ORM查询的情况一样,结果具有带键和值的 dict 属性

python sqlalchemy get column names dynamically?

答案 3 :(得分:1)

您可以使用dict(site)轻松地将每个结果行转换为字典。 如果site['ci']列存在,则ci可用。

为了site.ci(根据https://stackoverflow.com/a/22084672/487460):

from collections import namedtuple
Site = namedtuple('Site', site.keys())
record = Site(*site)

答案 4 :(得分:1)

我建立了一个简单的类,使其在我们的过程中像数据库界面一样工作。在这里:

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        

答案 5 :(得分:0)

我更喜欢创建具有列表理解能力的帮助器类和方法:

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]

答案 6 :(得分:0)

调用db.execute(sql).fetchall()时,可以轻松使用以下函数将返回数据解析为dict:

def query_to_dict(ret):
    if ret is not None:
        return [{key: value for key, value in row.items()} for row in ret if row is not None]
    else:
        return [{}]

答案 7 :(得分:0)

我发现的最简单的方法是使用列表理解并在每个 RowProxy 上调用 dict() 函数

site = db_session.execute(query)
result = [dict(row) for row in site]