Commited model.model_copy()
does not update the database accordingly #1398
-
First Check
Commit to Help
Example Codeimport pytest from sqlmodel import Field, Session, SQLModel, create_engine, select sqlite_file_name = "database.db" sqlite_url = f"sqlite:///{sqlite_file_name}" engine = create_engine(sqlite_url, echo=True) class Hero(SQLModel, table=True): id: int = Field(default=None, nullable=False, primary_key=True) name: str @pytest.fixture def create_and_teardown_db_and_tables(): SQLModel.metadata.create_all(engine) yield SQLModel.metadata.drop_all(engine) def test_hero_model_can_be_mutated_then_written_then_selected(create_and_teardown_db_and_tables): with Session(engine) as session: new_name = "Super-Michel" hero = Hero(id=1, name="Michel") hero.name = new_name session.add(hero) session.commit() session.refresh(hero) statement = select(Hero) results = session.exec(statement) retrieved_hero_object = results.one_or_none() # our object is up-to-date assert hero.name == new_name # the selected data from DB is up-to-date assert retrieved_hero_object.name == new_name def test_hero_model_can_be_copied_with_update_then_written_then_selected(create_and_teardown_db_and_tables): with Session(engine) as session: new_name = "Super-Michel" hero = Hero(id=1, name="Michel") hero_copy = hero.model_copy(update={"name": new_name}) session.add(hero_copy) session.commit() session.refresh(hero_copy) statement = select(Hero) results = session.exec(statement) retrieved_hero_object = results.one_or_none() # our object is up-to-date assert hero_copy.name == new_name # the selected data from DB is *NOT* up-to-date :'( assert retrieved_hero_object.name == new_name DescriptionWhen using Operating SystemLinux Operating System DetailsNo response SQLModel Version0.0.24 Python Version3.13.3 Additional ContextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
And these two tests are also failing 🤯 def test_hero_model_not_added_should_NOT_be_new_in_session(create_and_teardown_db_and_tables): with Session(engine) as session: new_name = "Super-Michel" hero = Hero(id=1, name="Michel") hero_copy = hero.model_copy(update={"name": new_name}) session.add(hero_copy) assert not hero in session.new def test_hero_model_added_should_be_new_in_session(create_and_teardown_db_and_tables): with Session(engine) as session: new_name = "Super-Michel" hero = Hero(id=1, name="Michel") hero_copy = hero.model_copy(update={"name": new_name}) session.add(hero_copy) assert hero_copy in session.new |
Beta Was this translation helpful? Give feedback.
-
hero_copy = session.merge(hero_copy) Important thing is that not Runnable code example in the details: import pytest from sqlmodel import Field, Session, SQLModel, create_engine, select sqlite_file_name = "database.db" sqlite_url = f"sqlite:///{sqlite_file_name}" engine = create_engine(sqlite_url, echo=True) class Hero(SQLModel, table=True): id: int = Field(default=None, nullable=False, primary_key=True) name: str @pytest.fixture def create_and_teardown_db_and_tables(): SQLModel.metadata.create_all(engine) yield SQLModel.metadata.drop_all(engine) def test_hero_model_can_be_mutated_then_written_then_selected(create_and_teardown_db_and_tables): with Session(engine) as session: new_name = "Super-Michel" hero = Hero(id=1, name="Michel") hero.name = new_name session.add(hero) session.commit() session.refresh(hero) statement = select(Hero) results = session.exec(statement) retrieved_hero_object = results.one_or_none() # our object is up-to-date assert hero.name == new_name # the selected data from DB is up-to-date assert retrieved_hero_object.name == new_name def test_hero_model_can_be_copied_with_update_then_written_then_selected(create_and_teardown_db_and_tables): with Session(engine) as session: new_name = "Super-Michel" hero = Hero(id=1, name="Michel") hero_copy = hero.model_copy(update={"name": new_name}) hero_copy = session.merge(hero_copy) session.commit() session.refresh(hero_copy) statement = select(Hero) results = session.exec(statement) retrieved_hero_object = results.one_or_none() # our object is up-to-date assert hero_copy.name == new_name # the selected data from DB is *NOT* up-to-date :'( assert retrieved_hero_object.name == new_name |
Beta Was this translation helpful? Give feedback.
session.add()
is used to add new object (which is not present in the DB).If you need to update existing object - use
session.merge()
:Important thing is that not
hero_copy
will be linked to the session, but it's copy. This is why we need to store the result ofsession.merge()
into variable to be able to refresh it later.Runnable code example in the details: