fastapi / sqlmodel

SQL databases in Python, designed for simplicity, compatibility, and robustness.
https://sqlmodel.tiangolo.com/
MIT License
14.45k stars 658 forks source link

🐛 Fix instance of related object added to session on validation #1052

Open mskrip opened 2 months ago

mskrip commented 2 months ago

Previously, when validating instance when a session was open and the model instance had a related object a new instance of this related object was created and added to the session.

I encountered similar issue described in https://github.com/tiangolo/sqlmodel/discussions/897 and narrowed it down to this replicatable issue:

from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, select

class Team(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str

    heroes: list["Hero"] = Relationship(
        back_populates="team",
    )

class Hero(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)

    name: str

    team_id: int | None = Field(default=None, foreign_key="team.id")
    team: Team | None = Relationship(back_populates="heroes")

if __name__ == "__main__":
    engine = create_engine(
        "postgresql+psycopg://<user>:<password>@localhost:5432/sqlmodel-test",
    )
    # SQLModel.metadata.create_all(engine)

    with Session(engine) as session:
        hero = session.exec(select(Hero)).one()
        print(f"{session.dirty=}")  # prints `session.dirty=IdentitySet([])`
        Hero.model_validate(hero, session=session)
        print(f"{session.dirty=}")  # prints `session.dirty=IdentitySet([Team(id=1, name='Team 1')])`