Subclass identification error on a one to one relationship. #1300
-
First Check
Commit to Help
Example Codefrom pydantic import BaseModel, computed_field, HttpUrl, model_serializer, model_validator
from typing import Annotated, Optional, Any, Self
from sqlalchemy.orm import Relationship
from sqlmodel import SQLModel, Field, BigInteger, AutoString
class Color(BaseModel):
red: int
green: int
blue: int
class User(SQLModel, table=True):
id: int = Field(primary_key=True, sa_type=BigInteger)
name: str
habitue: Optional["Habitue"] = Relationship(back_populates="user",uselist=False)
streamer: Optional["Streamer"] = Relationship(back_populates="user",uselist=False)
class Habitue(SQLModel, table=True):
id_: int | None = Field(primary_key=True, default=None)
user_id: int = Field(foreign_key="user.id", sa_type=BigInteger)
color: Color = Field(sa_type=AutoString)
user: User = Relationship(back_populates="habitue")
class Streamer(SQLModel, table=True):
id_: int | None = Field(primary_key=True, default=None)
user_id: int = Field(foreign_key="user.id", sa_type=BigInteger)
url: HttpUrl
user: User = Relationship(back_populates="streamer") We wanted to be as close as possible to this scenario, even if it's not the best way to do it with sql: CREATE TABLE user (
id BIGINT PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE habitue (
id_ SERIAL PRIMARY KEY,
user_id BIGINT UNIQUE NOT NULL,
color TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE
);
CREATE TABLE streamer (
id_ SERIAL PRIMARY KEY,
user_id BIGINT UNIQUE NOT NULL,
url TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE
); DescriptionWe have a User class with an Id and a name.To represent whether this user is a “Streamer” or a “Habitue”, we've defined two other classes with their own attributes. For us, a “User” has the optional ability to be a “Habitue” (A "Habitue" has a color) and/or a “Streamer” (a "Streamer" has a url). We therefore try to represent this link between a basic “User” and its advanced versions via a One-to-One relationship. We realize that at runtime, a type comparison is made. The “Streamer” and “Habitue” classes are not recognized as subclasses of the SQLModel type, but as Enums.As a result, we are unable to establish this One-to-One relationship.
To try to solve this, we tried the recommendations provided in:
Operating SystemLinux Operating System DetailsI'm running it in a python3.13 image docker SQLModel Version0.0.22 Python VersionPython 3.13.2 Additional ContextFull StackTrace:
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
You should import And then pass from sqlmodel import Relationship
...
habitue: Optional["Habitue"] = Relationship(back_populates="user", sa_relationship_kwargs={"uselist": False})
streamer: Optional["Streamer"] = Relationship(back_populates="user", sa_relationship_kwargs={"uselist": False}) Runnable code example in the details: from typing import Optional
from pydantic import BaseModel
from sqlmodel import (
AutoString,
BigInteger,
Field,
Relationship,
SQLModel,
create_engine,
)
class Color(BaseModel):
red: int
green: int
blue: int
class User(SQLModel, table=True):
id: int = Field(primary_key=True, sa_type=BigInteger)
name: str
habitue: Optional["Habitue"] = Relationship(
back_populates="user", sa_relationship_kwargs={"uselist": False}
)
streamer: Optional["Streamer"] = Relationship(
back_populates="user", sa_relationship_kwargs={"uselist": False}
)
class Habitue(SQLModel, table=True):
id_: int | None = Field(primary_key=True, default=None)
user_id: int = Field(foreign_key="user.id", sa_type=BigInteger)
color: Color = Field(sa_type=AutoString)
user: User = Relationship(back_populates="habitue")
class Streamer(SQLModel, table=True):
id_: int | None = Field(primary_key=True, default=None)
user_id: int = Field(foreign_key="user.id", sa_type=BigInteger)
...
user: User = Relationship(back_populates="streamer")
engine = create_engine(
"postgresql://user:mysecretpassword@localhost/some_db", echo=True
)
SQLModel.metadata.drop_all(engine)
SQLModel.metadata.create_all(engine) |
Beta Was this translation helpful? Give feedback.
You should import
Relationship
from sqlmodel, not from sqlalchemy.And then pass
uselist
viasa_relationship_kwargs
:Runnable code example in the details: