在SQLAlchemy中将查询结果作为字典检索

27

我正在使用flask SQLAlchemy,以下是从MySQL数据库中使用原始SQL查询获取用户的代码:

connection = engine.raw_connection()
cursor = connection.cursor()
cursor.execute("SELECT * from User where id=0")
results = cursor.fetchall()
< p > results 变量是一个元组,我想把它转换成字典类型。有什么方法可以实现吗?

当我使用 pymysql 建立数据库连接时,我能够做到:


当我使用pymysql建立数据库连接时,我能够这样做:

cursor = connection.cursor(pymysql.cursors.DictCursor)

SQLAlchemy中是否有类似的功能?

注意:我想做此更改的原因是,摆脱在我的代码中使用pymysql,并仅使用SQLAlchemy功能,即我不想在我的任何代码中使用´´´import pymysql´´´。


2
这回答解决了你的问题吗?将SQLAlchemy结果作为字典而不是列表返回 - Gord Thompson
1
不,我已经尝试过应用这个解决方案了,但它并没有像我在问题中提到的那样起作用。我正在使用engine.raw_connection,它返回元组而不是命名元组,你的评论IIja也同样适用。我收到了以下错误信息: AttributeError: 'tuple' object has no attribute '_asdict' - M.Alsioufi
1
我认为我的问题的旧标题更好地描述了我的需求。 - M.Alsioufi
@malsioufi 对,我完全忽略了你使用原始连接的事实,这使得我的先前评论无效。我也同意旧标题更合适。但一个好问题是:你为什么要使用原始连接? - Ilja Everilä
我正在将我的应用程序从使用pymysql更新为使用SQLAlchemy。在代码中的许多地方都使用了以下代码:cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute(some_statment) 因此,我认为如果有一种方法可以暂时保持这种行为,并仅将连接对象(conn)从pymysql对象更新为SQLAlchemy对象即可。换句话说,我想保留这部分代码:cursor = connection.cursor() cursor.execute("SELECT * from User where id=0") results = cursor.fetchall()``` - M.Alsioufi
出于好奇,您有什么值得分享的理由不使用pymysql吗? - Zubo
4个回答

63
结果是一个元组,我希望它是字典类型。 SQLAlchemy 1.4更新的答案: 版本1.4已经废弃了旧的engine.execute()模式并改变了.execute()在内部的操作方式。.execute()现在返回一个CursorResult对象,其中包含一个.mappings()方法:
import sqlalchemy as sa

# …

with engine.begin() as conn:
    qry = sa.text("SELECT FirstName, LastName FROM clients WHERE ID < 3")
    resultset = conn.execute(qry)
    results_as_dict = resultset.mappings().all()
    pprint(results_as_dict)
    """
    [{'FirstName': 'Gord', 'LastName': 'Thompson'}, 
     {'FirstName': 'Bob', 'LastName': 'Loblaw'}]
    """

(SQLAlchemy 1.3 的以前的回答)

如果你使用 engine.execute 而不是 raw_connection(),SQLAlchemy 已经为你做了这个。使用 engine.executefetchone 将返回一个 SQLAlchemy 的 Row 对象,fetchall 将返回一个包含多个 Row 对象的 list。可以通过键访问 Row 对象,就像访问一个 dict 一样:

sql = "SELECT FirstName, LastName FROM clients WHERE ID = 1"
result = engine.execute(sql).fetchone()
print(type(result))  # <class 'sqlalchemy.engine.result.Row'>
print(result['FirstName'])  # Gord

如果您需要一个真正的 dict 对象,那么您只需进行转换:

my_dict = dict(result)
print(my_dict)  # {'FirstName': 'Gord', 'LastName': 'Thompson'}

我实际上正在将我的应用程序从使用pymysql更新为使用SQLAlchemy,并且在代码的许多地方中使用了以下内容:cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute(some_statment)因此,我想知道是否有一种方法可以暂时保持这种行为,只需将连接对象(conn)从pymysql对象更新为SQLAlchemy对象即可。这就是为什么我不想使用engine.execute()解决问题的原因,因为这需要我对代码进行很多更改,而我现在不想这样做。 - M.Alsioufi
这仅适用于顶级选择字段,而不适用于聚合器,例如 func.array_agg - 如何使其也适用于那些呢? - user2340939

2
你可以使用SQLAlchemy的游标和游标描述。

def rows_as_dicts(cursor):
    """convert tuple result to dict with cursor"""
    col_names = [i[0] for i in cursor.description]
    return [dict(zip(col_names, row)) for row in cursor]


db = SQLAlchemy(app)
# get cursor
cursor = db.session.execute(sql).cursor
# tuple result to dict
result = rows_as_dicts(cursor)


1
如果raw_connection()返回的是PyMySQL Connection对象,那么您可以继续像这样使用DictCursor:
engine = create_engine("mysql+pymysql://root:whatever@localhost:3307/mydb")
connection = engine.raw_connection()
cursor = connection.cursor(pymysql.cursors.DictCursor)
cursor.execute("SELECT 1 AS foo, 'two' AS bar")
result = cursor.fetchall()
print(result)  # [{'foo': 1, 'bar': 'two'}]

我认为我的问题中缺少了一些东西(我现在会添加),我想在代码中的任何地方都不使用pymysql,因为SQLAlchemy在幕后使用它。但是目前似乎不可能这样做。 - M.Alsioufi

-2

我个人会使用pandas:

import pandas as pd
connection = engine.raw_connection()
df = pd.read_sql_query('SELECT * from User where id=0' , connection)
mydict = df.to_dict()

我实际上正在将我的应用程序从使用pymysql更新为使用SQLAlchemy,并且在代码的许多地方使用了以下语句:cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute(some_statment)因此,我想知道是否有一种方法可以暂时保持这种行为,只需将连接对象(conn)从pymysql对象更新为SQLAlchemy对象即可。这就是为什么我不想使用engine.execute()解决问题的原因,因为这需要我对代码进行很多更改,而我现在不想这样做。 - M.Alsioufi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接