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

FastAPI使用Tortoise-ORM写入外键字段报AttributeError错如何解决

问题根因

你触发报错的核心原因是Tortoise-ORM对外键字段的自动命名规则:

  • 你在project模型中定义的外键字段名为user_id,Tortoise会自动为该外键对应的数据库ID字段追加_id后缀,实际映射的数据库存值字段为user_id_id
  • 你直接给user_id参数传整数1,Tortoise会把这个值当成UserModel实例来解析,自然就触发了int对象没有_saved_in_db属性的报错
  • 额外注意:create方法已经自动执行了数据保存操作,后续再调用await project.save()属于冗余操作,可以直接删除

修复方案

方案1:传实际的UserModel实例

先查询到对应的用户实例,再传给外键字段:

@auth_router.post("/add_project")
async def register(form_data: users.project = Depends()):
    # 先查询对应ID的用户实例
    user = await UserModel.get(id=1)
    # 将实例传给外键字段
    project = await users.project.create(project_name=form_data.project_name, user_id=user)

方案2:直接传外键ID值(更高效,不需要额外查询)

用Tortoise自动生成的带_id后缀的字段名传ID值:

@auth_router.post("/add_project")
async def register(form_data: users.project = Depends()):
    # 外键字段名追加_id后传整数ID即可
    project = await users.project.create(project_name=form_data.project_name, user_id_id=1)

可选优化(避免后续命名混淆)

建议修改模型中的外键字段名,不要带_id后缀,符合Tortoise的命名规范:

# 修改后的project模型
class project(models.Model):
    id = fields.IntField(pk=True)
    project_name = fields.CharField(null=False, max_length=255)
    # 外键字段名改为user,不要带_id
    user = fields.ForeignKeyField(
        "models.UserModel", related_name="items", null=True)

修改后你就可以直接用符合直觉的user_id=1传ID值:

project = await users.project.create(project_name=form_data.project_name, user_id=1)

内容的提问来源于stack exchange,提问作者Sandeepkumar Bandi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 02:30:03