Skip to content
Prev Previous commit
Next Next commit
creates temp UpdateModel to avoid issues with SQLModel's serializatio…
…n settings like `include` and `exclude`
  • Loading branch information
A00474880 committed May 7, 2026
commit ac676fbf62a8442631cffcab08754b06436a81ee
16 changes: 15 additions & 1 deletion sqlmodel/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
overload,
)

from pydantic import BaseModel, EmailStr
from pydantic import BaseModel, EmailStr, create_model
from pydantic.fields import FieldInfo as PydanticFieldInfo
from sqlalchemy import (
Boolean,
Expand Down Expand Up @@ -1007,6 +1007,20 @@ def sqlmodel_update(
f"is not a dict or SQLModel or Pydantic model: {obj}"
)
if isinstance(obj, BaseModel):
# Create a temp UpdateModel schema (removes extra serialization settings)
ObjClass = obj.__class__
fields_def = {
fname: finfo.annotation
for fname, finfo in ObjClass.model_fields.items()
}
UpdateModel = create_model(
f"_{ObjClass.__name__}Update_", **fields_def
)
# rebuild obj instance with model_construct
obj = UpdateModel.model_construct(
_fields_set=obj.model_fields_set, **obj.__dict__
)
# Now `obj.model_dump` works with **model_dump_kwargs
obj = obj.model_dump(**model_dump_kwargs)
Comment on lines +1011 to +1024
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break use cases with models that have fields with exclude=True:

from sqlmodel import Field, SQLModel


class Item(SQLModel):
    id: str
    param: str = Field(exclude=True)


a = Item.model_validate({"id": "1", "param": "1"})
b = Item.model_validate({"id": "1", "param": "2"})


a.sqlmodel_update(b, exclude={"id"})
# a.sqlmodel_update(b)


assert a.param == "2"

.. and probably some other cases when model has settings that change the default serialization schema.

use_update = (update or {}).copy()
for key, value in {**obj, **use_update}.items():
Expand Down