Relationships¶
Relationships are declared with Relationship(...) as
a field default and loaded explicitly via db.related(). Relationship fields are
never persisted — only the foreign-key column is stored.
from tinystore import Relationship
class Post(Model):
id: int | None = Field(default=None, primary_key=True)
title: str
author_id: int = Field(foreign_key="users.id")
author: User | None = Relationship(foreign_key="author_id")
Load a related object:
Cardinality¶
The cardinality is inferred from which side holds the FK:
- many-to-one (local FK):
db.related(post, "author")-> single instance orNone. - one-to-many (remote FK):
db.related(user, "posts")-> list of instances.
The side is determined automatically from the declared foreign_key; if multiple
models reference the same table ambiguously, RelationshipError is raised.
A full example¶
class User(Model):
id: int | None = Field(default=None, primary_key=True)
name: str
class Post(Model):
id: int | None = Field(default=None, primary_key=True)
title: str
author_id: int = Field(foreign_key="users.id", on_delete="CASCADE")
author: User | None = Relationship(foreign_key="author_id")
Declare the relationship on whichever side you want to traverse from. To go from a user to their posts without declaring a reverse relationship, use a join (see the Joins guide) or query directly:
Relationships vs. joins¶
- Use a
Relationshipwhen you have a clear "parent" object and want to follow one FK to its target (or to its dependents). - Use a join when you want to combine rows from multiple tables into a single result set.