You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask-SQLAlchemy查询无结果(数据库存在对应数据),修改数据库路径后出现JSON序列化错误

Flask-SQLAlchemy查询无结果(数据库存在对应数据),修改数据库路径后出现JSON序列化错误

我正在开发第一个结合SQLite数据库的Flask应用,遇到了两个棘手的问题:明明数据库里有对应数据,但SQLAlchemy的查询却返回空列表;修改数据库路径后,又出现了JSON序列化错误。下面是我的详细情况和问题细节:

数据库与数据情况

我的数据库是test_db,里面有一张test_table表,结构如下:

  • fruit_name TEXT NOT NULL
  • order_amount INTEGER NOT NULL
  • store_id INTEGER NOT NULL

表中已经存入了3条记录:

  • orange, 100, 5
  • apple, 250, 8
  • peach, 347, 7

初始代码实现

导入与数据库配置

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test_db.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

注:test_db.db和Python文件放在同一目录下

数据库模型类

因为没有手动设置主键,我想用SQLite自带的_rowid_作为主键,所以模型类写成这样:

class testTable(db.Model):
    _rowid_ = db.Column(db.Integer, primary_key=True)
    fruit_name = db.Column(db.TEXT)
    order_amount = db.Column(db.INTEGER)
    store_id = db.Column(db.INTEGER)

    def __init__(self, fruit_name, order_amount, store_id):
        self.fruit_name = fruit_name
        self.order_amount = order_amount
        self.store_id = store_id

路由与查询逻辑

我写了一个简单的路由,查询fruit_name为"orange"的记录并返回:

@app.route('/')
def home():
    query_result = testTable.query.filter(testTable.fruit_name == "orange").all()
    return query_result

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)

之前看到资料说Flask-SQLAlchemy会把下划线命名的表转为驼峰式,所以我觉得查询部分是没问题的,但启动后页面只显示[],完全查不到数据。

后续更新:修改数据库路径后的新错误

根据建议修改了SQLALCHEMY_DATABASE_URI的路径后,查询空的问题没解决,反而出现了新的JSON序列化错误,完整报错信息如下:

Traceback (most recent call last):
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\app.py", line 2213, in __call__
return self.wsgi_app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\app.py", line 2193, in wsgi_app
response = self.handle_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\app.py", line 1487, in full_dispatch_request
return self.finalize_request(rv)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\app.py", line 1506, in finalize_request
response = self.make_response(rv)
^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\app.py", line 1820, in make_response
rv = self.json.response(rv)
^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\json\provider.py", line 215, in response
f"{self.dumps(obj, **dump_args)}\n", mimetype=self.mimetype
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\json\provider.py", line 180, in dumps
return json.dumps(obj, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lnb2628\AppData\Local\Programs\Python\Python311\Lib\json\__init__.py", line 238, in dumps
**kw).encode(obj)
^^^^^^^^^^^   
File "C:\Users\Lnb2628\AppData\Local\Programs\Python\Python311\Lib\json\encoder.py", line 202, in encode
chunks = list(chunks)
^^^^^^^^^^^^
File "C:\Users\Lnb2628\AppData\Local\Programs\Python\Python311\Lib\json\encoder.py", line 430, in _iterencode
yield from _iterencode_list(o, _current_indent_level)
File "C:\Users\Lnb2628\AppData\Local\Programs\Python\Python311\Lib\json\encoder.py", line 326, in _iterencode_list
yield from chunks
File "C:\Users\Lnb2628\AppData\Local\Programs\Python\Python311\Lib\json\encoder.py", line 439, in _iterencode
o = _default(o)
^^^^^^^^^^^
File "c:\Users\Lnb2628\OneDrive\Documents\Python Projects\flask_practice\practice_env\Lib\site-packages\flask\json\provider.py", line 120, in _default
raise TypeError(f"Object of type {type(o).name} is not JSON serializable") 
TypeError: Object of type testTable is not JSON serializable

问题排查与解决方案

1. 先解决查询无结果的核心问题

查询返回空列表,大概率是模型类和实际数据库表的映射不匹配导致的,我帮你梳理几个关键点:

  • 主键定义问题:SQLite的_rowid_是隐式列,不需要手动在模型类中定义,手动定义反而可能导致映射异常。建议手动添加一个主键列,比如id = db.Column(db.Integer, primary_key=True)。
  • 表名映射歧义:虽然Flask-SQLAlchemy默认会把testTable转为test_table,但显式指定表名更稳妥,避免自动转换的意外。
  • 字段类型规范:SQLAlchemy的字段类型应该用小写开头的写法,比如db.Text、db.Integer,虽然大小写可能不影响,但规范写法能避免潜在问题。
  • 数据库文件确认:确认你的test_db.db是你手动添加了数据的那个文件——有时候db.create_all()会在当前目录创建一个新的空数据库,如果之前的数据在另一个文件里,自然查不到。

修改后的模型类可以改成这样:

class testTable(db.Model):
    __tablename__ = 'test_table'  # 显式指定表名,消除歧义
    id = db.Column(db.Integer, primary_key=True)  # 手动定义主键
    fruit_name = db.Column(db.Text, nullable=False)
    order_amount = db.Column(db.Integer, nullable=False)
    store_id = db.Column(db.Integer, nullable=False)

    def __repr__(self):
        return f"<testTable {self.fruit_name}>"  # 方便调试时查看对象内容

2. 解决JSON序列化错误

当你直接返回query_result(一个包含testTable对象的列表)时,Flask会尝试把它序列化为JSON,但Python对象默认不能直接转为JSON,所以才出现了序列化错误。这里有几种简单的解决方式:

方式一:直接将对象转为字典返回

修改路由函数,把查询到的每个对象转为字典:

@app.route('/')
def home():
    query_result = testTable.query.filter(testTable.fruit_name == "orange").all()
    # 把每个对象的字段转为字典
    result_list = [
        {
            'fruit_name': item.fruit_name,
            'order_amount': item.order_amount,
            'store_id': item.store_id
        } for item in query_result
    ]
    return result_list

方式二:在模型类中添加序列化方法

在testTable类中添加一个to_dict方法,专门返回对象的字典表示:

class testTable(db.Model):
    __tablename__ = 'test_table'
    id = db.Column(db.Integer, primary_key=True)
    fruit_name = db.Column(db.Text, nullable=False)
    order_amount = db.Column(db.Integer, nullable=False)
    store_id = db.Column(db.Integer, nullable=False)

    def to_dict(self):
        return {
            'id': self.id,
            'fruit_name': self.fruit_name,
            'order_amount': self.order_amount,
            'store_id': self.store_id
        }

    def __repr__(self):
        return f"<testTable {self.fruit_name}>"

然后在路由中调用这个方法:

@app.route('/')
def home():
    query_result = testTable.query.filter(testTable.fruit_name == "orange").all()
    return [item.to_dict() for item in query_result]

3. 额外调试建议

可以在路由中添加打印语句,方便排查问题:

@app.route('/')
def home():
    query = testTable.query.filter(testTable.fruit_name == "orange")
    print(query.statement)  # 打印生成的SQL语句,确认是否正确
    query_result = query.all()
    print(query_result)  # 打印查询结果,看是否为空
    result_list = [item.to_dict() for item in query_result]
    return result_list

备注:内容来源于stack exchange,提问作者Lnb2628

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 11:58:02