-
First Check
Commit to Help
Example Codefrom decimal import Decimal
from sqlmodel import __version__, SQLModel, Field
class Foo(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
enabled: bool = Field(default=False)
count: int = Field(default=0, ge=0)
gauge: Decimal = Field(default=Decimal('0.00'),
ge=Decimal('0.00'))
if __name__ == '__main__':
print(f'sqlmodel.{__version__=}')
foo_1 = Foo(enabled=True, count=1234, gauge=Decimal('56.78'))
print(f'{foo_1=}')
d = dict(enabled='True', count='1234', gauge='56.78')
print(f'{d=}')
foo_2 = Foo(**d)
print(f'{foo_2=}')
# Using SQLModel 0.0.8, foo_1 and foo_2 are equal
# Using SQLModel 0.0.19, attributes of foo_2 are all strings DescriptionMy codebase commonly constructs SQLModel-subclassed objects from dictionaries with string keys and values, such as provided by csv.DictReader objects, by unpacking the dictionary within the invocation of the object constructor, as illustrated in the code above. For that code, the output using 0.0.8 is:
You can see that objects foo_1 and foo_2 are equivalent. I have just upgraded to 0.0.19 and expected that this code pattern would continue to work without modification. Nevertheless, I have found that that pattern no longer converts the dictionary values to the respective attribute types specified in the class definition. Running precisely the same code using 0.0.19, the output is:
You can see that object foo_1 unsurprisingly behaves as before, but surprisingly foo_2's attributes are all strings rather than the various numerical values expected. This is causing widespread failure in my codebase. Operating SystemLinux Operating System DetailsFedora 40 SQLModel Version0.0.19 Python Version3.12.4 Additional ContextI have created a nearly identical test file using pydantic BaseModel directly. The dict-unpacking-in-contstructor pattern works identically between pydantic versions 1.10.8 (which I was using before my upgrade) and 2.8.2 (which I am using now). I have loved using FastAPI and SQLModel. Thank you immensely for these fantastic tools! I look forward to whatever insights you can offer so I can continue learning about, experimenting with, and leveraging your excellent work. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I just did some intermediate testing of sqlmodel versions between 0.0.8 and 0.0.19 and discovered that the dict-unpacking-in-constructor pattern started failing for my code above beginning in version 0.0.14. If I hold sqlmodel at 0.0.14 but use pydantic 1.10.17 with it rather than pydantic 2.8.2 (which is what pip preferred to give me), my code works. I've confirmed that sqlmodel 0.0.19 works as expected as long as it's on pydantic 1.10.17. Consequently, it seems that integration between sqlmodel and pydantic 2.8.2 does not handle my code pattern. I've also confirmed the code pattern fails with sqlmodel 0.0.19 for every version of pydantic from 2.5.2 (which looked to be the first 2.x version integrated with) up to 2.8.2, so this behavioral variance appears to stem from the earliest days of the 2.x integration; it is not a new development. I will update the title of this discussion to better reflect this finding. |
Beta Was this translation helpful? Give feedback.
In the hopes that others will benefit, I'm documenting what I believe to be the right approach for my situation. Rather than this pattern (from the code above):
...this pattern achieves my aim:
It's only a little more verbose, and the updates to my codebase, while not small in number, are nicely surgical.
Happy coding!