Replies: 19 comments
-
|
To guess, when used as a table object, there is no verification process because it is used to map data that has already been verified in database. I've asked the same question before, but I'm just using |
Beta Was this translation helpful? Give feedback.
-
|
I do understand that too, reads from database don't need validation. But writes do. Nevertheless it's not really clear in the documentation. |
Beta Was this translation helpful? Give feedback.
-
|
@deajan |
Beta Was this translation helpful? Give feedback.
-
|
I think this is answered here: #52 (comment) For future reference, I found this while looking for why |
Beta Was this translation helpful? Give feedback.
-
|
This feature/bug should be fully documented, as I (and many others) expect the SQL model to validate data. Only after doing a lot of digging to find out why one of my field_validator wasn't working did I come across this GitHub issue. |
Beta Was this translation helpful? Give feedback.
-
|
I agree - this just totally threw me off. I expected it to be fully validating my table data. why bother inheriting from BaseModel at all if not.
|
Beta Was this translation helpful? Give feedback.
-
|
completely annoying bug. I've lost half a day trying to understand what was happening. I'll reconsider if SQLModel is actually the way to go. Thank you, guys! |
Beta Was this translation helpful? Give feedback.
-
|
This was also very surprising to me. Looks like this PR may fix the issue, although it's unclear if it's the right approach. |
Beta Was this translation helpful? Give feedback.
-
|
when update new version ? |
Beta Was this translation helpful? Give feedback.
-
I don't think, that there will be a version fixing this. It rather looks like, that this oddity is considered a feature. Sadly. |
Beta Was this translation helpful? Give feedback.
-
|
That's not what I expected. I mean, I don't consider myself a senior so I guess whoever is working on it knows better than me but: My problem was really stupid. class Formula(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
formula: str
I can't use |
Beta Was this translation helpful? Give feedback.
-
|
The whole point for me of considering SQLModel was to avoid duplication required by the mapping from my data model (type checking with Pydantic) to the mapping of my database model (ORM). If this is not a bug, then SQLModel is totally useless. |
Beta Was this translation helpful? Give feedback.
-
|
I see I'm late to this party after many hours spent banging my head against a wall in my code base. The fascinating part is that the model validators are called with from datetime import datetime as dt
from datetime import timezone as tz
from typing import Annotated, Self
from pydantic import BeforeValidator
from sqlmodel import Field, SQLModel
IntDatetime = Annotated[
dt,
BeforeValidator(lambda x: dt.fromtimestamp(x / 1000, tz=tz.utc) if isinstance(x, int) else x),
]
class ExampleWorks(SQLModel):
time: IntDatetime = Field(primary_key=True)
class ExampleBroken(SQLModel, table=True):
time: IntDatetime = Field(primary_key=True)
class NastyBase(SQLModel):
@classmethod
def model_validate_json(cls, json: str | bytes) -> Self:
model = super().model_validate_json(json)
return cls.model_validate(model)
class ExampleBrokenFixed(NastyBase, table=True):
time: IntDatetime = Field(primary_key=True)
print("Without a table, validation works:")
print(ExampleWorks(time=dt(2025, 8, 14, tzinfo=tz.utc)))
print(ExampleWorks.model_validate({"time": 1755129600000}))
print(ExampleWorks.model_validate_json('{"time": 1755129600000}'))
print("\nMaking it a table breaks validation:")
print(ExampleBroken(time=dt(2025, 8, 14, tzinfo=tz.utc)))
print(ExampleBroken.model_validate({"time": 1755129600000}))
print(ExampleBroken.model_validate_json('{"time": 1755129600000}'))
print("\nForcing revalidation makes this slow but it technically works:")
print(ExampleBrokenFixed(time=dt(2025, 8, 14, tzinfo=tz.utc)))
print(ExampleBrokenFixed.model_validate({"time": 1755129600000}))
print(ExampleBrokenFixed.model_validate_json('{"time": 1755129600000}'))Outputs: |
Beta Was this translation helpful? Give feedback.
-
|
Well, it was really unpleasant to discover... The whole point of the library, to combine pydantic and sqlalchemy, seems to have failed. This example prints from datetime import datetime
from fastapi import FastAPI
from sqlmodel import Field, SQLModel
import uvicorn
app = FastAPI()
class FavoriteDate(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
date: datetime
@app.post("/date")
async def add_date(favorite_date: FavoriteDate):
print(type(favorite_date.date))
uvicorn.run(app, port=5000) |
Beta Was this translation helpful? Give feedback.
-
|
Pasting the TL;DR from here TL;DRYou don't need multi-models. Here's a complete solution to address the problems: Derive from this base (modify |
Beta Was this translation helpful? Give feedback.
-
To me, the whole point of using a library is to avoid digging in its protected attributes and private methods. Running undocumented code in an untested way based on a comment in a Github thread dosen't feel appealing. This is the first paragraph of the README :
I surely don't understand all the pros and cons of this library as it is used by a lot of people, but my usecase, which I thought simple, isn't covered. Seeing the hundreds of reactions and the number of issues opened on this subject, I would say something isn't working as people expected. Maybe it should be made clear from the start that this usecase is not covered, and that people will need to write separate classes extending eachother to manage the validation and the orm separately. The README says it "combines" pydantics and SQLAlchemy but it is unclear to me how it combines them. In any case, thank you for your work, provided for free to me and others. I hope I'll find another usecase for it. |
Beta Was this translation helpful? Give feedback.
-
|
I just would like to make this absolutely clear. The library claims (statement) to combine pydantic and sqlalchemy models, but in its very basic use-case it doesn't validate the request against the model when used with FastAPI which defeats the purpose. Even the code from the simple api tutorial returns a 500 internal error instead of a 422 validation error. This is the very first endpoint users create with the library, so either the library description should be updated with corrected claims, or it should be made clear from get-go that defining a class with # great simple way of processing the Hero class
@app.post("/heroes/")
def create_hero(hero: Hero):
with Session(engine) as session:
session.add(hero)
session.commit()
session.refresh(hero)
return heroPlease don't get me wrong, the library is great in the fact that I don't need to deal with sqlalchemy types and simply create a pydantic model and interact with the database. But I still need a separate model to first validate the user input. The final list of models becomes something like below, see my comments please. # common fields
class HeroBase(SQLModel):
name: str = Field(index=True)
secret_name: str
age: int | None = Field(default=None, index=True)
# database model
class Hero(HeroBase, table=True):
id: int | None = Field(default=None, primary_key=True)
# model for post requests
class HeroCreate(HeroBase):
pass
# model for responses
# practically the same as Hero but reasons ...
class HeroPublic(HeroBase):
id: int |
Beta Was this translation helpful? Give feedback.
-
|
"Hi, I've opened a PR to address the documentation gap mentioned here: #1880" |
Beta Was this translation helpful? Give feedback.
-
Hey @shubhamyx, |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
First Check
Commit to Help
Example Code
Description
When creating a SQLModel class instance, I thought that I'd have all the advantages of pydantic and SQLAlchemy classes toghether.
I was quite surprised when I realized that SQLModel classes created with
table=Truedo not validate data as a pydantic class would do (see my example code).Having read about all SQLModel documentation, I didn't find anywhere this is stated.
Especially in https://sqlmodel.tiangolo.com/tutorial/fastapi/multiple-models/ it would make sense to explain that a
table=Truewon't do data validation as a pydantic class would do.Maybe I did not understand the purpose of SQLModel enough, but this is quite disturbing for me.
I think it would be really nice to update the documentation regarding this particular point.
Operating System
Windows
Operating System Details
No response
SQLModel Version
0.0.8
Python Version
Python 3.10.7 x64
Additional Context
PS: Sorry, I'm comming here from Tortoise-ORM, and it's my first time using SQLModel, so I cannot guarantee that I will be quite helpful resolving issues here yet ;) I'll do my best.
Beta Was this translation helpful? Give feedback.
All reactions