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

SQLModel使用defer/load_only仍返回主键ID,如何原生规避?

SQLModel查询无法排除主键id字段的原生解决方案

问题描述

定义了如下SQLModel模型:

from typing import Optional
from sqlmodel import SQLModel, Field

class UserBase(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    JWT: str
    password: str

尝试通过仅加载JWT字段或使用defer(UserBase.id)排除id时,SQLModel始终会在查询中包含userbase.id,返回结果也会带上id字段,目前只能通过手写SQL解决,希望找到原生处理方式。

原生处理方式

1. 直接指定查询字段

在select语句中明确指定需要的字段,而非查询整个模型,这样生成的SQL只会包含目标字段:

from sqlmodel import select, Session

# 仅查询JWT字段
stmt = select(UserBase.JWT)
with Session(engine) as session:
    jwt_list = session.exec(stmt).all()

生成的SQL为:SELECT userbase."JWT" FROM userbase,不会包含id。

2. 使用with_only_columns修改现有查询

如果已经有基于UserBase的查询语句,可通过with_only_columns替换查询的字段列表:

stmt = select(UserBase).with_only_columns(UserBase.JWT)
jwt_list = session.exec(stmt).all()

3. 为什么defer无法排除主键?

SQLModel底层依赖SQLAlchemy,而ORM框架中主键是对象实例的核心标识,默认不可延迟加载。即使调用defer(UserBase.id),ORM依然会强制加载主键以维持对象的完整性,因此这种方式无法排除id字段。

4. 如需返回模型实例(不含id)

可以定义一个只读的无主键模型,将查询结果映射到该模型:

class UserJWTOly(SQLModel):
    JWT: str

# 查询并映射结果
with Session(engine) as session:
    result_mappings = session.exec(select(UserBase.JWT)).mappings().all()
    jwt_instances = [UserJWTOly(**mapping) for mapping in result_mappings]

内容的提问来源于stack exchange,提问作者Mr. Cocodrilo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:34:58