SQLModel继承问题:BaseUser中Role字段无法在AppUser中填充
解决SQLModel继承基类中Relationship不生效的问题
问题原因
SQLModel 0.0.12中,标记为table=False的基类里定义的Relationship不会自动被继承到子类的表模型中。这是因为ORM映射构建逻辑仅处理当前表类直接定义的关系配置,非表基类中的关系不会被纳入子类的映射元数据。
解决方案
方案一:使用declared_attr动态定义关系
通过SQLAlchemy的declared_attr装饰器,让基类中的关系在子类继承时被正确生成并注册到ORM映射中:
from sqlmodel import Field, SQLModel, Column from sqlalchemy import create_engine from sqlalchemy.orm import relationship, declared_attr from sqlalchemy.pool import StaticPool from typing import Optional from sqlalchemy import BigInteger from sqlmodel import Relationship, Session, select class Base(SQLModel, table=False): id: Optional[int] = Field(sa_column=Column(BigInteger(), default=None, primary_key=True)) class UserRole(Base, table=True): name: str class BaseUser(Base, table=False): username: str role_id: int = Field(default=None, foreign_key="userrole.id") @declared_attr def role(cls): return Relationship(sa_relationship=relationship("UserRole", lazy="joined")) class AppUser(BaseUser, table=True): email: str engine = create_engine( 'sqlite:///demo2.db', connect_args={"check_same_thread": False}, poolclass=StaticPool, echo=True ) SQLModel.metadata.create_all(engine) with Session(engine) as session: statement = select(AppUser) results = session.exec(statement) items = results.all()
方案二:子类显式复用基类关系定义
如果不想使用declared_attr,可以在子类中直接引用基类的role属性,避免重复编写关系配置:
class AppUser(BaseUser, table=True): email: str role: UserRole = BaseUser.role
原理说明
declared_attr会在子类创建时动态生成关系属性,确保SQLModel的ORM映射系统能识别并处理这个关联。- 直接引用基类的
role属性,相当于将基类的关系配置复制到子类中,让SQLModel在处理子类表模型时,将该关系纳入映射元数据。
内容的提问来源于stack exchange,提问作者Gabriel Macus
相关产品推荐
相关产品推荐

