Skip to main content
In this lesson we replace the in-memory Faker-based generator with a small SQLite-backed repository and wire that repository into a FastAPI endpoint. This gives deterministic, realistic records for testing and demonstrates proper database connection handling, parameter binding, and package import considerations. Overview
  • Start: existing FastAPI endpoint used the Faker library to produce fake values.
  • Goal: read rows from a local SQLite database (fakedata.db) and return full records: first name, last name, email, age, city, occupation.
  • Key troubleshooting items fixed:
    • Database file path (working directory differences).
    • Connection lifecycle (closing connections too early).
    • Correct binding of LIMIT in SQLite queries.
    • Relative import/module path issues in package layouts.
  • Architecture: a small repository module handles DB access while a thin router calls the repository.
Note on tools
Use tools like GitHub Copilot to speed development, but always validate generated code. Pay special attention to imports, file layout, DB paths, and the connection lifecycle.
Initial Faker-based endpoint (before wiring to DB)
Why switch to SQLite?
  • Deterministic test data: a small SQLite DB produces repeatable records (useful for tests and demos).
  • Realism: returns full records matching your schema, rather than single fake attributes.
  • Education: demonstrates repository patterns, SQL parameter binding, correct connection handling.
Repository: data/fake_data_repository.py
  • This module contains all DB logic: creating a connection and retrieving records.
  • Important: do not close the connection in get_db_connection() before returning it. Close connections after use in the caller (or in finally blocks inside repository functions).
Final repository implementation:
Router: api/endpoints/router.py
  • Keep the endpoint thin and delegate DB interactions to the repository.
  • The request model is a simple Pydantic model containing just count (and an optional locale retained for compatibility).
Request model: api/models/fake_data_request.py
  • After switching to full-record retrieval, data_type was no longer needed. Keep locale optional for backward compatibility.
Common troubleshooting steps and fixes Diagnostic SQL and verification
  • Use the sqlite CLI or DB Browser for SQLite to confirm schema:
    • PRAGMA table_info(fake_data);
  • Example schema verification output:
Debugging tips used
  • Print the SQL and DB path before executing to confirm behavior:
  • Run the printed SQL directly in DB Browser or the sqlite3 CLI to validate results.
  • From your application, run PRAGMA table_info(fake_data); to verify the schema accessible to your running process.
Example request / response (final implementation) Request body:
Response body:
Notes about package imports and running the app
  • If you hit ModuleNotFoundError for top-level package names like src, prefer relative imports or ensure the working directory/PYTHONPATH is set to the project root containing api/ and data/.
  • The examples above use api.models... and data.fake_data_repository assuming you run the app from the project root.
Warning about over-reliance on code generation tools
Automatic code tools (e.g., GitHub Copilot) can speed development, but they may:
  • Introduce unexpected file-layout or import changes.
  • Create new files in the wrong locations if the tool lacks full project context.
  • Generate code that looks correct but has runtime issues (e.g., closing connections too early, wrong DB path). Always review generated suggestions, run tests, and validate runtime behavior.
What we achieved
  • Replaced a Faker-based generator with a DB-backed repository that returns real rows.
  • Implemented a clean separation: thin router -> repository -> DB.
  • Resolved DB location, parameter binding, and connection lifecycle issues.
  • Documented troubleshooting steps to help diagnose similar issues quickly.
Next steps
  • Add query parameters to filter by fields (e.g., age range, city).
  • Implement pagination instead of relying on ORDER BY RANDOM() LIMIT ? for large tables.
  • Consider caching or a lightweight connection pool for heavier workloads (SQLite is best for small datasets/testing).
Example utility to inspect the DB (for local debugging)
Closing thoughts
  • This lesson demonstrates wiring a FastAPI endpoint to a local SQLite database, covering common pitfalls and fixes.
  • Use automation tools to assist, but validate structure, imports, and runtime behavior yourself.
Links and references

Watch Video