【问题标题】:TypeError: Object of type RowProxy is not JSON serializable - FlaskTypeError:RowProxy 类型的对象不是 JSON 可序列化的 - Flask
【发布时间】:2020-09-05 22:06:21
【问题描述】:

我正在使用 SQLAlchemy 使用引擎从我的 Flask Web 应用程序中查询数据库。在我执行 SELECT Query 并在返回 ResultProxy 后使用 fetchall 对象最终返回 RowProxy 对象然后我存储在会话中。 这是我的代码:

import os
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from flask import Flask, session
engine = create_engine(os.environ.get('DATABASE_URL'))
db = scoped_session(sessionmaker(bind=engine))

app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY')
@app.route('/')
def index():
    session['list'] = db.execute("SELECT title,author,year FROM books WHERE year = 2011 LIMIT 4").fetchall()
    print(session['list'])
    return "<h1>hello world</h1>"


if __name__ == "__main__":
    app.run(debug = True)

这是输出:

[('Steve Jobs', 'Walter Isaacson', 2011), ('Legend', 'Marie Lu', 2011), ('Hit List', 'Laurell K. Hamilton', 2011), ('Born at Midnight', 'C.C. Hunter', 2011)]
Traceback (most recent call last):
  File "C:\Users\avise\AppData\Local\Programs\Python\Python38\Lib\site-packages\flask\app.py", line 2463, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\avise\AppData\Local\Programs\Python\Python38\Lib\site-packages\flask\app.py", line 2449, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\avise\AppData\Local\Programs\Python\Python38\Lib\site-packages\flask\app.py", line 1866, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\avise\AppData\Local\Programs\Python\Python38\Lib\json\encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type RowProxy is not JSON serializable

会话项存储数据,正如我在输出中看到的那样。但是“hello world”没有呈现。 如果我用普通变量 x 替换会话变量,那么它似乎正在工作。 但我认为我需要使用会话,以便用户同时使用我的应用程序来显示不同的内容。那么,在这种情况下我怎么能使用会话,或者还有其他方法吗? 任何帮助将不胜感激,因为我是 Flask 和网络开发的新手。

【问题讨论】:

    标签: session flask sqlalchemy


    【解决方案1】:

    根据我对 Flask Session 对象的了解,它充当 python 字典;但是值必须是 JSON 可序列化的。在这种情况下,就像错误提示的那样,fetch all 返回的 RowProxy 对象不是 json 可序列化的。

    解决此问题的方法是将查询结果作为字典(可序列化 JSON)传递。

    您的查询结果似乎返回了一个元组列表,因此我们可以执行以下操作:

    res = db.execute("SELECT title,author,year FROM books WHERE year = 2011 LIMIT 4").fetchall()
    user_books = {}
    index = 0
    for entry in res:
        user_books[index] = {'title':res[index][0],
            'author':res[index][1],
            'year':res[index][2],
            }
        index += 1
    
    session['list'] = user_books
    

    请注意;但是,是因为我们使用书名作为key,如果有两本书同名,信息可能会被覆盖,所以考虑使用唯一的id作为key。

    另请注意,上面的字典结构仅适用于您已有的查询 - 如果您在 select 语句中添加了另一列,则必须编辑代码以包含额外的列信息。

    【讨论】:

    • 非常感谢,因为你将 rowproxy 对象作为 dict 键,所以我进行了一些编辑,以便将来有人可以得到帮助。
    猜你喜欢
    • 2022-01-26
    • 2021-09-24
    • 2019-03-05
    • 2019-07-12
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    相关资源
    最近更新 更多