sqlmodel icon indicating copy to clipboard operation
sqlmodel copied to clipboard

✨ Ensure that type checks are executed when setting `table=True`

Open monchin opened this issue 1 year ago • 11 comments

I found that when table=True is set, pydantic becomes invalid for usage like hero = Hero(name="Deadpond", secret_name="Dive Wilson", age="test"). As the document says you get all of Pydantic's features, including automatic data validation, serialization, and documentation. You can use SQLModel in the same way you can use Pydantic., I think table=True makes pydantic invalid is a bug, so I tried to fix it.

I delete a test case because this case is incompatible with pydantic. I also add a test case to ensure my code works. For current code, my new test case would fail, but it would pass for my new code.

monchin avatar Aug 01 '24 03:08 monchin

Some related issues for this one:

However, I think this comment indicates that this is actually the desired behavior.

iloveitaly avatar Nov 26 '24 21:11 iloveitaly

this is actually the desired behavior

I regard this action as a bug rather than a feature because sqlmodel announce that you get all of Pydantic's features, including automatic data validation, serialization, and documentation. You can use SQLModel in the same way you can use Pydantic. Models with no validation when table=True is definitely not the way we are using pydantic.

monchin avatar Nov 27 '24 07:11 monchin

Hi all, is there a plan to merge this? Currently facing the same issues discussed in #11 and #453 (and several other related issues) and none of the proposed workaround seem clean enough for my use case.

Thanks.

muhammadyaseen avatar Dec 16 '24 15:12 muhammadyaseen

@tiangolo Would you please look at this PR snd see whether this solution is OK? It passes all tests.

monchin avatar Dec 17 '24 09:12 monchin

Hey, bumping this because we urgently need it as well :)

Thanks!

ohadc-orchid avatar Jan 27 '25 11:01 ohadc-orchid

@ohadc-orchid

Fortunately, there seems to be an easy solution.

class Config:
        validate_assignment = True
from datetime import datetime

from pydantic import BaseModel
from sqlmodel import SQLModel, Field


class DatetimeModel(BaseModel):
    timestamp: datetime

class DatetimeSQLModel(SQLModel):
    id: str = Field("dummy", primary_key=True)
    timestamp: datetime

class DatetimeSQLTableModel(SQLModel, table=True):
    id: str = Field("dummy", primary_key=True)
    timestamp: datetime
    class Config:
        validate_assignment = True

t = '2024-11-13T12:30:12.584245Z'
m1 = DatetimeModel(timestamp=t)
m2 = DatetimeSQLModel(timestamp=t)
m3 = DatetimeSQLTableModel(timestamp=t)

print(type(m1.timestamp))
print(type(m2.timestamp))
print(type(m3.timestamp))

if __name__ == '__main__':
    pass

aedan-chiari avatar Jan 30 '25 17:01 aedan-chiari

Bumping this. I get @tiangolo 's intention, but it seems that things are naturally leaning in another direction. If nothing is wrong with this implementation, then I think it's a huge step forward.

paulomtts avatar Apr 08 '25 14:04 paulomtts

@ohadc-orchid

Fortunately, there seems to be an easy solution.

class Config:
        validate_assignment = True
from datetime import datetime

from pydantic import BaseModel
from sqlmodel import SQLModel, Field


class DatetimeModel(BaseModel):
    timestamp: datetime

class DatetimeSQLModel(SQLModel):
    id: str = Field("dummy", primary_key=True)
    timestamp: datetime

class DatetimeSQLTableModel(SQLModel, table=True):
    id: str = Field("dummy", primary_key=True)
    timestamp: datetime
    class Config:
        validate_assignment = True

t = '2024-11-13T12:30:12.584245Z'
m1 = DatetimeModel(timestamp=t)
m2 = DatetimeSQLModel(timestamp=t)
m3 = DatetimeSQLTableModel(timestamp=t)

print(type(m1.timestamp))
print(type(m2.timestamp))
print(type(m3.timestamp))

if __name__ == '__main__':
    pass

This works for type validations(as PR aims to fix) but it is not very helpful if you want to use field validators, please see the comment: https://github.com/fastapi/sqlmodel/issues/52#issuecomment-2372511953

Just wanted to point it out if someone ends up here looking for how to work with field or model validators like me.

furkansenol avatar Apr 09 '25 08:04 furkansenol

this is actually the desired behavior

I regard this action as a bug rather than a feature because sqlmodel announce that you get all of Pydantic's features, including automatic data validation, serialization, and documentation. You can use SQLModel in the same way you can use Pydantic. Models with no validation when table=True is definitely not the way we are using pydantic.

Agree with this interpretation, but at the same time the code seems to explicitly try to avoid that behaviour (https://github.com/fastapi/sqlmodel/blob/main/sqlmodel/_compat.py#L564). Would love some clarity from the FastAPI folks on the intention here. This was definitely the most surprising behaviour I noticed using SQLModel.

vimota avatar Jun 01 '25 06:06 vimota

Hi all!

The current behaviour is clearly intentional, as stated in the docs and the code, and as further explained by Tiangolo here.

As such, I think it's unlikely that Tiangolo will want to change this behaviour. Nevertheless, I'll request his feedback internally.

Personally I think that if we choose to keep the current behaviour, we should consider adding more detailed documentation (and examples) about this functionality, as it's clearly unintuitive for many users.

svlandeg avatar Oct 07 '25 09:10 svlandeg