Relationships¶
This guide demonstrates relationship annotations and explicit loading.
What The Example Covers¶
- scalar relationship fields;
- collection relationship fields;
- relationship-derived hydration;
- joined and select-in loading;
- avoiding hidden lazy I/O.
"""Relationship loading example."""
import asyncio
from pydantic import BaseModel, Field
from ormdantic import Ormdantic, lazyload, selectinload
db = Ormdantic("sqlite:///examples_relationships.sqlite3")
@db.table(pk="id")
class Flavor(BaseModel):
id: str
name: str
@db.table(pk="id")
class Coffee(BaseModel):
id: str
name: str
flavor: Flavor | str = Field(...)
async def main() -> None:
await db.init()
await db.drop_all()
await db.create_all()
flavor = Flavor(id="flavor-1", name="mocha")
await db[Flavor].insert(flavor)
await db[Coffee].insert(Coffee(id="coffee-1", name="latte", flavor=flavor))
loaded = await db[Coffee].find_one("coffee-1", depth=1)
assert loaded is not None
assert isinstance(loaded.flavor, Flavor)
selected = await db[Coffee].find_one("coffee-1", load=[selectinload("flavor")])
assert selected is not None
assert selected.flavor == flavor
shallow = await db[Coffee].find_one("coffee-1", load=[lazyload("flavor")])
assert shallow is not None
assert await db.load(shallow, "flavor") == flavor
if __name__ == "__main__":
asyncio.run(main())
Run it locally:
python examples/relationships.py
Choosing A Loader¶
Use joinedload for small related row sets where one joined query is efficient. Use selectinload for collections and larger graphs where batched secondary queries are easier to control.