Starlette/FastAPI集成SQLite报no such table:PersonDetail错误
问题根因
报错本质是三个代码逻辑错误,和你之前确认存在的表无关:
- 重复定义
declarative_base()实例:main.py和schemas.py各自新建了独立的Base对象,启动时执行建表逻辑用的是main.py里没有挂载任何模型的空Base,根本不会创建PersonDetail表。 - SQLite数据库使用相对路径:程序启动时的工作目录不同,会在对应目录下生成全新的空数据库文件,你确认存在表的数据库文件,和程序实际连接的不是同一个。
- 全局提前初始化数据库Session:模块加载时就创建了固定Session连接,后续表结构变更、数据库文件切换后,旧连接不会自动更新,持续读取空库。
修复步骤
按顺序修改对应文件即可:
- 统一Base实例定义,修改
db.py,把Base的定义收敛到数据库配置文件,同时把SQLite地址改成绝对路径,避免路径错位:
from sqlalchemy.orm import Session, declarative_base from sqlalchemy import create_engine import os # 全局唯一的Base实例 Base = declarative_base() # 拼接数据库文件绝对路径,固定存放在db.py同目录下 DB_FILE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "PersonalDetail.db") engine = create_engine( f"sqlite:///{DB_FILE_PATH}", connect_args={"check_same_thread": False}, echo=True ) def get_session(): with Session(engine) as session: yield session
- 修改
schemas.py,从db.py导入统一的Base,不要自行新建Base实例:
from sqlalchemy import Column, Integer, String from db import Base class PersonDetail(Base): __tablename__ = 'PersonDetail' id = Column(Integer, primary_key=True) name = Column(String)
- 修改
main.py,导入统一的Base实例,启动前提前加载模型元数据,同时修正uvicorn启动的模块路径:
import uvicorn from starlette.applications import Starlette from starlette.routing import Route from API.get import GetMethod from API.post import PostMethod from db import engine, Base # 提前导入模型,保证Base能识别到PersonDetail表的定义 import schemas routes = [ Route("/get", endpoint=GetMethod, methods=["GET"]), Route("/post", endpoint=PostMethod, methods=["POST"]), ] app = Starlette(routes=routes) @app.on_event("startup") def on_startup(): Base.metadata.create_all(engine) if __name__ == "__main__": # 原代码写的carsharing:app和当前文件名不匹配,会导致启动找错应用对象 uvicorn.run("main:app", reload=True)
- 修改
get.py,去掉全局初始化的Session,每次请求时新建会话,同时处理ORM对象的序列化问题:
from starlette.requests import Request from starlette.responses import JSONResponse from db import engine from schemas import PersonDetail from sqlalchemy.orm import Session def GetMethod(request): with Session(bind=engine, expire_on_commit=False) as local_session: result = local_session.query(PersonDetail).all() # 直接返回ORM对象会触发序列化报错,转成字典格式再返回 return JSONResponse([ {"id": item.id, "name": item.name} for item in result ])
修复完成后,先把项目目录下所有零散的
PersonalDetail.db文件全部删除,再重新启动服务,程序会在db.py所在目录生成带PersonDetail表的正确数据库文件,不会再出现表不存在的报错。
内容的提问来源于stack exchange,提问作者SPMK
相关产品推荐
相关产品推荐

