FastAPI + SQLite Application

Serve SQLSpec-backed content through FastAPI using the synchronous SQLite adapter.

uv run python docs/examples/frameworks/fastapi/sqlite_app.py

Source

 1"""FastAPI application backed by SQLSpec and SQLite."""
 2
 3import asyncio
 4from collections.abc import Iterator
 5from typing import Annotated, Any
 6
 7from fastapi import Depends, FastAPI
 8
 9from docs.examples.shared.configs import sqlite_registry
10from docs.examples.shared.data import ARTICLES, CREATE_ARTICLES
11from sqlspec.adapters.sqlite import SqliteConfig, SqliteDriver
12from sqlspec.core import SQL
13
14__all__ = ("get_session", "list_articles", "main", "on_startup", "seed_database")
15
16
17registry = sqlite_registry()
18config = registry.get_config(SqliteConfig)
19app = FastAPI()
20
21
22def seed_database() -> None:
23    """Create the demo schema and seed rows."""
24    with config.provide_session() as session:
25        session.execute(CREATE_ARTICLES)
26        for row in ARTICLES:
27            session.execute(
28                SQL(
29                    """
30                    INSERT OR REPLACE INTO articles (id, title, body)
31                    VALUES (:id, :title, :body)
32                    """
33                ),
34                row,
35            )
36
37
38@app.on_event("startup")
39async def on_startup() -> None:
40    """Seed data when the ASGI app boots."""
41    await asyncio.to_thread(seed_database)
42
43
44def get_session() -> "Iterator[SqliteDriver]":
45    """Yield a synchronous SQLite driver for request handlers."""
46    with config.provide_session() as session:
47        yield session
48
49
50@app.get("/articles")
51def list_articles(db_session: Annotated["SqliteDriver", Depends(get_session)]) -> "list[dict[str, Any]]":
52    """Return all demo articles sorted by ID."""
53    result = db_session.execute("SELECT id, title, body FROM articles ORDER BY id")
54    return result.all()
55
56
57def main() -> None:
58    """Seed the database without running the ASGI server."""
59    seed_database()
60
61
62if __name__ == "__main__":
63    main()