【问题标题】:Retrieve query results as dict in SQLAlchemy在 SQLAlchemy 中以 dict 形式检索查询结果
【发布时间】:2020-02-27 17:15:27
【问题描述】:

我正在使用flask SQLAlchemy,并且我有以下代码通过来自MySQL数据库的原始SQL查询从数据库中获取用户:

connection = engine.raw_connection()
cursor = connection.cursor()
cursor.execute("SELECT * from User where id=0")
results = cursor.fetchall()

results 变量是一个元组,我希望它是 dict() 类型。有没有办法做到这一点?

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

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

SQLAlchemy 中有类似的东西吗?

注意:我想要进行此更改的原因是为了摆脱在我的代码中使用 pymysql,而只使用 SQLAlcehmy 功能,即我不想在我的代码中的任何地方都有 ´´´import pymysql´´´。

【问题讨论】:

  • 不,我已尝试应用此解决方案,但它不起作用,正如我在问题中提到的那样,我正在使用 engine.raw_connection,它返回未命名元组的元组,同样适用于您的评论 IIja 我收到此错误消息 AttributeError : 'tuple' 对象没有属性 '_asdict'
  • 我认为我的问题的旧标题更好地描述了我的需求
  • @malsioufi 对,完全错过了您使用原始连接的事实,这使我之前的评论无效。我也同意旧标题更合适。但是一个很好的问题是:为什么要使用原始连接?
  • 我正在做的是将我的应用程序从使用 pymysql 更新为使用 SQLAlchemy。在代码中的许多地方都使用了cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute(some_statment) ,所以我认为是否有办法暂时保持这种行为,只需将连接对象(conn)从pymysql对象更新为SQLAlchemy对象。也就是说,我想保留这部分python cursor = connection.cursor() cursor.execute("SELECT * from User where id=0") results = cursor.fetchall()

标签: python mysql sqlalchemy flask-sqlalchemy


【解决方案1】:

results 是一个元组,我希望它是 dict() 类型

SQLAlchemy 1.4 的更新答案:

1.4 版已弃用旧的engine.execute() 模式并更改了.execute() 在内部的运行方式。 .execute() 现在返回带有 .mappings() 方法的 CursorResult 对象:

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 将返回 listRow 对象。 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。并且在代码中的许多地方都使用了python cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute(some_statment) ,所以我想是否有办法暂时保持这种行为,只需将连接对象(conn)从pymysql对象更新为SQLAlchemy对象。这就是为什么我不想用 engine.execute() 来解决这个问题,因为这需要我在我的代码中做很多我现在不想做的更改
【解决方案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)

【讨论】:

    【解决方案3】:

    如果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 在后台使用它。但现在似乎不可能这样做。
    【解决方案4】:

    我个人会使用 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。并且在代码中的许多地方都使用了python cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute(some_statment) ,所以我想是否有办法暂时保持这种行为,只需将连接对象(conn)从pymysql对象更新为SQLAlchemy对象。这就是为什么我不想用 engine.execute() 来解决这个问题,因为这需要我在我的代码中做很多我现在不想做的更改
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 2014-03-13
    • 2018-03-02
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 2017-09-09
    相关资源
    最近更新 更多