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

FastAPI+SQLAlchemy删除数据报错:int对象无_sa_instance_state属性

FastAPI删除接口SQLAlchemy错误解决方法

问题描述

在FastAPI中实现删除博客的接口时,出现以下错误:

AttributeError: 'int' object has no attribute '_sa_instance_state'

The above exception was the direct cause of the following exception:

sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.int' is not mapped

对应代码如下:

from fastapi import FastAPI, Depends, status
from sqlalchemy.orm import Session
from typing import List
from database import engine, SessionLocal
from models import Blog, User
from fastapi import HTTPException
import schemas,models

app = FastAPI()

def getdb():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close

models.Base.metadata.create_all(engine) #migrating

@app.get('/blog')
def all_blogs(db: Session = Depends(getdb)):
    db_blog = db.query(Blog).all()
    return db_blog

@app.get('/user')
def all_users(db: Session = Depends(getdb)):
    db_blog= db.query(User).all()
    return db_blog

@app.post('/blog', status_code= status.HTTP_201_CREATED)
def create_blog(blog: schemas.BlogCreate, db: Session = Depends(getdb)):
    db_blog = Blog(title=blog.title, user_id = blog.user_id)
    db.add(db_blog)
    db.commit()
    db.refresh(db_blog)
    return db_blog


@app.post('/user', status_code= status.HTTP_201_CREATED)
def create_user(user: schemas.UserCreate, db: Session = Depends(getdb)):
    db_user = User(name = user.name)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user

@app.delete('/blog/{blog_id}', status_code= status.HTTP_204_NO_CONTENT)
def destroy(blog_id, db:Session = Depends(getdb)):
    db_blog = db.query(Blog).filter(Blog.id == blog_id).delete(synchronize_session="evaluate")
    db.commit()
    db.refresh(db_blog)
    return f"{Blog.id} deleted"


@app.get('/blog/{blog_id}', response_model=schemas.Blog)
def show_blog(blog_id: int, db: Session = Depends(getdb)):
    db_blog = db.query(Blog).filter(Blog.id == blog_id).first()
    if not db_blog:
        raise HTTPException(status_code=404, detail='Blog not found')
    return db_blog

@app.get('/user/{user_id}', response_model=schemas.User)
def show_user(user_id: int, db: Session = Depends(getdb)):
    db_user = db.query(User).filter(User.id == user_id).first()
    if not db_user:
        raise HTTPException(status_code=404, detail='Blog not found')
    return db_user

错误原因

  1. delete()返回值类型错误:query.filter(...).delete()返回的是被删除的记录行数(整数),而非Blog模型实例。后续调用db.refresh(db_blog)时,refresh需要传入ORM实例,传入整数必然触发错误。
  2. 参数类型未声明:blog_id未指定类型,FastAPI默认将其解析为字符串,可能导致与数据库中整数类型的id匹配异常。
  3. 违反HTTP状态码规范:HTTP 204状态码要求响应体为空,代码中返回字符串不符合该规范。
  4. 返回内容错误:Blog.id是模型类的属性,并非具体记录的id,无法正确显示被删除的博客ID。

修复方案

方案1:先查询实例再删除(推荐)

这种方式可以先验证记录是否存在,再执行删除操作:

@app.delete('/blog/{blog_id}', status_code=status.HTTP_204_NO_CONTENT)
def destroy(blog_id: int, db: Session = Depends(getdb)):
    # 查询目标博客
    db_blog = db.query(Blog).filter(Blog.id == blog_id).first()
    if not db_blog:
        raise HTTPException(status_code=404, detail='Blog not found')
    
    # 删除实例并提交
    db.delete(db_blog)
    db.commit()
    
    # 204状态码无需返回内容
    return

方案2:直接执行删除并检查行数

如果不需要先查询实例,可以通过删除行数判断操作是否成功:

@app.delete('/blog/{blog_id}', status_code=status.HTTP_204_NO_CONTENT)
def destroy(blog_id: int, db: Session = Depends(getdb)):
    deleted_count = db.query(Blog).filter(Blog.id == blog_id).delete(synchronize_session="evaluate")
    if deleted_count == 0:
        raise HTTPException(status_code=404, detail='Blog not found')
    
    db.commit()
    return

修复要点总结

  • 为blog_id添加int类型声明,确保参数类型与数据库字段匹配。
  • 移除db.refresh()调用,删除后的实例无需刷新。
  • 验证记录是否存在,避免无意义的删除操作并返回友好提示。
  • 遵循HTTP 204状态码规范,不返回任何响应内容。

内容的提问来源于stack exchange,提问作者Ashutosh Singh Khadka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:05:11