4 ms·
Just looking at SQLModel example at (1) class Hero(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) name: str
by kristianp 2y ago
Just looking at SQLModel example at (1)
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
Is the id supposed to be an Optional like that?
(1) https://sqlmodel.tiangolo.com/ https://sqlmodel.tiangolo.com/
- globular-toast 2y agoI think because you can create an object before you persist it in the db. The db will generate the id for you. So id=None is used to mean "not in persistent storage".
- valbaca 2y agousually the ORM generates the id, so it's None until saved (at least I'm assuming based on how other ORMs often (not always!) work)
- instig007 2y agoNo, it's a bad design that doesn't use type composition to restrict invalid representations. People are given type hints, but they still practice the same dynamic typing mistakes as before, including the authors of the lib. Instead, it should distinguish between persisted entities and value objects: class Entity(Generic[A]): pk: int val: A class Hero: name: str secret_name: str age: None | int = None class Service(Generic[A]): def persist(self, x: A) -> Entity[A]: pk = self.execute(insert(x)) return Entity(pk, x) def select(self, *cond) -> Iterable[Entity[A]]: ... def copy(self, x: Entity[A]) -> Entity[A]: return self.persist(x.val) def delete(self, pk_ent: int | Entity[A]) -> A: ... It should be obvious how the same model extends to different PK types too: serial ints, UUIDs, etc.