| ▲ | roel_v 4 hours ago | |||||||||||||
Why would one want to couple these two? Doesn't that couple, say, your API interface with your database schema? Whereas in reality these are separate concepts, even if, yes, sometimes you return a 'user' from an API that looks the same as the 'user' in the database? Honest question, I only just recently got into FastAPI and I was a bit confused at first that yes, it seemed like a lot of duplication, but after a little bit of experience, they are different things that aren't always the same. So what am I missing? | ||||||||||||||
| ▲ | mr_Fatalyst 4 hours ago | parent | next [-] | |||||||||||||
The ORM doesn't force you to use the DB model as your API schema. It's a regular Pydantic BaseModel, so you can make separate request/response schemas whenever you need to. For simple CRUD, using the model directly saves boilerplate. For complex cases, you decouple them as usual. The goal is not one model for everything, it's one contract. Everything speaks Pydantic, whether it's your API layer or your database layer. | ||||||||||||||
| ▲ | miki123211 2 hours ago | parent | prev | next [-] | |||||||||||||
I think they should be related but not the same. With proper DRY, you shouldn't need to repeat the types, docstrings and validation rules. You should be able to say "these fields from user go on its default presenter, there are two other presenters with extra fields" without having to repeat all that info. I have a vague memory that Django Rest Framework does something of the sort. This feels hard to express in modern type systems though. Perhaps the craziness that is Zod and Typescript could do it, but probably not Python. | ||||||||||||||
| ▲ | giovannibonetti 2 hours ago | parent | prev | next [-] | |||||||||||||
You might be interested in a library that flips around the concept of an ORM, like sqlc [1] or aiosql [2]. You specify just what you want from the database, without needing to couple so much API with database tables. [1] https://sqlc.dev/ [2] https://nackjicholson.github.io/aiosql/ | ||||||||||||||
| ▲ | ElectricalUnion an hour ago | parent | prev | next [-] | |||||||||||||
I also find it really strange this weird ORM fascination. Besides the generic "ORM are the Vietnam War of CS" feeling, I feel that with average database to ORM/REST things, end up with at least one of: a) you somehow actually have a "system of record", so modelling something in a very CRUD way makes sense, but, on the other hand, who the hell ends up building so many system of record systems in the first place to need those kinds of tools and frameworks? b) you pretend your system is somehow a system of record when it isn't and modelling everything as CRUD makes it a uniform ball of mud. I don't understand what is so important that you can uniformly "CRUD" a bunch of objects? The three most important parts of an API, making it easy to use it right, hard to use it wrong, and easy to figure out the intent behind how your system is meant to be used, are lost that way. c) you leak your API to your database, or your database to your API, compromising both, so both sucks. | ||||||||||||||
| ||||||||||||||
| ▲ | whinvik 3 hours ago | parent | prev | next [-] | |||||||||||||
Yeah I have always struggled to figure out why I would use SQLModel. Big fan of FastAPI but I think SQLModel leads to the wrong mental model that somehow db model and api schema are the same. Therefore I insist on using SQLAlchemy for db models and pydantic for api schemas as a mental boundary. | ||||||||||||||
| ▲ | Onavo 2 hours ago | parent | prev [-] | |||||||||||||
With this you don't need to have two sources of truth on the backend. Previously you will end up with one set of DB ORM level validation and a second set of validation on the data transfer object and you have to make sure the types line up. Now the data transfer object will automatically inherit the correct types. | ||||||||||||||
| ||||||||||||||