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
相关产品推荐
相关产品推荐

