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

使用Python Tortoise ORM更新关联UserInfo模型时出现操作错误

通过Tortoise ORM关联更新PostgreSQL数据时的错误排查

问题场景

我用Tortoise ORM操作PostgreSQL,定义了一对OneToOne关联的模型:

class User(Model):
    class Meta:
        table = "users"

    id = fields.UUIDField(primary_key=True)
    internal_id = fields.IntField(unique=True)
    info: fields.ReverseRelation["UserInfo"]

class UserInfo(Model):
    class Meta:
        table = "user_infos"

    id = fields.UUIDField(primary_key=True)
    rank = fields.IntField()
    user = fields.OneToOneField("app.User", related_name="info")

尝试通过用户的internal_id更新UserInfo时触发错误:

await UserInfo.filter(user__internal_id=SOME_ID).update(rank=5)

错误信息:

tortoise.exceptions.OperationalError: invalid reference to FROM-clause entry for table "user_infos"
HINT:  There is an entry for table "user_infos", but it cannot be referenced from this part of the query.

生成的错误SQL:

UPDATE "user_infos" SET "rank"=$1 FROM "user_infos" "user_infos_" LEFT OUTER JOIN "users" "user_infos__user" ON "user_infos__user"."id"="user_infos"."user_id" WHERE "user_infos__user"."internal_id"=893706004;

单独执行过滤查询能正常返回UserInfo对象:

await UserInfo.filter(user__internal_id=internal_id)

错误原因

Tortoise ORM生成的更新SQL存在逻辑错误:在FROM子句里重复引入了user_infos表(别名user_infos_),同时主更新表也是user_infos。PostgreSQL在这种情况下无法正确解析主表和FROM子句中同表的引用关系,因此抛出错误。

而查询操作时,Tortoise生成的是标准的JOIN查询,不会重复引入目标表,所以能正常执行。

解决方案

方案1:通过反向关联从User模型发起更新

利用OneToOne字段定义的related_name="info",直接从User模型出发关联更新UserInfo:

await User.filter(internal_id=SOME_ID).update(info__rank=5)

方案2:先获取目标用户ID再更新

先查询到目标用户的ID,再用该ID过滤UserInfo进行更新:

# 方式1:先查询用户对象
target_user = await User.get(internal_id=SOME_ID)
await UserInfo.filter(user_id=target_user.id).update(rank=5)

# 方式2:用子查询直接过滤
await UserInfo.filter(user_id=User.filter(internal_id=SOME_ID).values("id")).update(rank=5)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:42:17