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: