SQLModel behaves differently from Pydantic BaseModel in exclude_unset

Question:

I have the following code snippet

class Model(BaseModel):
    is_required: float
    a_float: Optional[float] = None
    k: Optional[int] = None


k = Model(
    **{
        "is_required": 0.1,
        "a_float": 1.2,
    }
)
print(k.dict()) #{'is_required': 0.1, 'a_float': 1.2, 'k': None}
print(k.dict(exclude_unset=True)) #{'is_required': 0.1, 'a_float': 1.2}

This is understandable. But once I switch to SQLModel using the following code, the result changed for exclude_unset.

class Model(SQLModel):
    is_required: float
    a_float: Optional[float] = None
    k: Optional[int] = None

k = Model(
    **{
        "is_required": 0.1,
        "a_float": 1.2,
    }
)
print(k.dict()) #{'is_required': 0.1, 'a_float': 1.2, 'k': None}
print(k.dict(exclude_unset=True)) #{'is_required': 0.1, 'a_float': 1.2, 'k': None}

Why does this happen, and is there a way for me to get a dict where unsets are not included in the export using dict()?

Asked By: nuitnuit

||

Answers:

EDIT: this has been fixes as of SQLModel version 0.0.7.

Original answer:
I looked into this a bit, and as of today (version 0.0.6), SQLModel.dict(exclude_unset=True) simply does not work as intended, at least when instantiated using the normal constructor. There is an open GitHub issue about this, and a PR that addresses it.

My guess would be that FastAPI (which clearly is the "intended usecase" of SQLModel) uses some variant of the from_orm method, because this code works:

from types import SimpleNamespace
from typing import Optional

from sqlmodel import SQLModel

class Model(SQLModel):
    is_required: float
    kasdf: Optional[int] = None
    a_float: Optional[float] = None

k = Model.from_orm(SimpleNamespace(is_required=0.1, a_float=1.2))
print(k2.dict())  # {'is_required': 0.1, 'a_float': 1.2, 'k': None}
print(k2.dict(exclude_unset=True))  # {'is_required': 0.1, 'a_float': 1.2}

Here I’m using SimpleNamespace, which is simply a way to create an object with the provided names as fields

s = SimpleNamespace(foo=3, bar="value")
print(s.foo)  # 3
print(s.bar)  # 'value'
Answered By: M.O.
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.