使用SqlAlchemy与FastAPI出现Internal Server Error,求协助排查
问题分析与解决方案
核心错误点
数据库表创建位置错误
你把Base.metadata.create_all(bind=engine)写在了Books类内部,这会导致表创建逻辑在类定义阶段就执行,不符合规范且可能引发初始化问题。需将其移到所有模型类定义完成之后。接口返回值错误
add_book函数最后返回Books(**b1.dict()),这是新建了一个未关联数据库会话的ORM对象,正确做法是返回已提交并刷新过的bk对象,它包含数据库返回的最新状态。会话变量命名冲突
将sessionmaker创建的工厂命名为session,和sqlalchemy.orm.Session类重名,容易混淆,建议改为SessionLocal。
修改后的完整代码
from fastapi import FastAPI, Depends import uvicorn from pydantic import BaseModel from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.ext.declarative import declarative_base SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db" engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) # 重命名会话工厂,避免与Session类冲突 SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() class Books(Base): __tablename__ = 'book' id = Column(Integer, primary_key=True, nullable=False) title = Column(String(50), unique=True) author = Column(String(50)) publisher = Column(String(50)) # 将表创建逻辑移至所有模型定义之后 Base.metadata.create_all(bind=engine) class Book(BaseModel): id: int title: str author: str publisher: str class Config: orm_mode = True app = FastAPI() def get_db(): db = SessionLocal() # 使用重命名后的会话工厂 try: yield db finally: db.close() @app.post('/add_new', response_model=Book) def add_book(b1: Book, db: Session = Depends(get_db)): bk = Books(id=b1.id, title=b1.title, author=b1.author, publisher=b1.publisher) db.add(bk) db.commit() db.refresh(bk) return bk # 返回已关联数据库的对象
额外说明
当前SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"是正确的,它会在当前目录创建test.db文件。若需修改路径,比如将数据库放在项目根目录的data文件夹下,可改为sqlite:///./data/test.db(需确保data文件夹已存在)。
运行修改后的代码,在Swagger页面(默认http://localhost:8000/docs)测试/add_new接口,即可正常返回结果,不再出现Internal Server Error。
内容的提问来源于stack exchange,提问作者bravopapa
相关产品推荐
相关产品推荐

