A robust FastAPI application demonstrating user registration, JWT authentication (including refresh tokens), and a flexible repository pattern supporting SQLite, PostgreSQL, and MongoDB backends.
This project serves as a template or starting point for building secure and scalable FastAPI applications with a focus on:
- Clean Architecture: Separation of concerns using API routes, core logic, database repositories, and Pydantic schemas.
- Flexibility: Easily switch between SQL (SQLite/PostgreSQL) and NoSQL (MongoDB) databases via configuration.
- Modern Tooling: Utilizes
uv
for dependency management,Dynaconf
for configuration, andruff
for linting/formatting. - Testability: Designed with dependency injection and includes a comprehensive test suite using
pytest
.
- JWT-based authentication (login, refresh tokens).
- User registration with password hashing (bcrypt) and validation.
- Protected user profile endpoint (
/users/me
). - Flexible database layer using the Repository Pattern.
- Configuration management with
Dynaconf
(settings.toml
,.secrets.toml
, environment variables withFAPI_
prefix). - Asynchronous support throughout (FastAPI, database drivers).
- Automated API documentation (Swagger UI & ReDoc).
- Comprehensive test suite with
pytest
(including coverage). - Health check endpoint (
/health
).
Below is an overview of the application's architecture:
- Python: >= 3.13
- Framework: FastAPI (>=0.115.12)
- Authentication: python-jose (JWT), passlib, bcrypt
- Database ORM/Driver:
- SQLAlchemy (>=2.0.40) for SQL databases
- Motor (>=3.5.0, via
mongodb_repository.py
, requires separate install if used) for MongoDB - Psycopg2 (requires separate install if using PostgreSQL)
- aiosqlite (>=0.20.0, requires separate install if using async SQLite
sqlite+aiosqlite
)
- Configuration: Dynaconf (>=3.2.0)
- Testing: pytest, pytest-asyncio, pytest-cov, httpx
- Dependency Management: uv
- Linting/Formatting: Ruff
/
├── app/ # Main application module
│ ├── api/ # API endpoints (routers)
│ ├── core/ # Core logic (config, security, exceptions)
│ ├── db/ # Database interaction layer (repositories, models, session)
│ └── schemas/ # Pydantic schemas (data validation)
├── config/ # Configuration files
│ ├── .secrets.toml # Secret settings (JWT secret, DB passwords) - DO NOT COMMIT
│ ├── .secrets.toml.example # Example secrets file
│ └── settings.toml # Main application settings (DB type, etc.)
├── tests/ # Application tests (mirrors app structure)
│ └── conftest.py # Pytest configuration and fixtures
├── .gitignore # Git ignore rules
├── main.py # FastAPI application entry point
├── pyproject.toml # Project metadata and dependencies (uv)
├── README.md # This file
├── run_tests.sh # Helper script for running tests
├── test.db # Default SQLite database file (if used)
└── uv.lock # Lock file for dependencies (uv)
Below is a preview of the application's interface:
-
Clone the repository:
git clone <your-repo-url> cd fapi
-
Create and activate a virtual environment:
python -m venv .venv source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
-
Install dependencies (using uv):
# Install core dependencies uv pip install -e . # Install all dependencies including test extras uv pip install -e '.[test]' # Install DB-specific drivers if needed (not included by default) # uv pip install psycopg2-binary # For PostgreSQL # uv pip install motor # For MongoDB # uv pip install aiosqlite # For async SQLite
-
Configure Settings:
-
Settings are managed by
Dynaconf
, loading fromconfig/settings.toml
,config/.secrets.toml
, and environment variables (prefixed withFAPI_
, e.g.,FAPI_DATABASE_TYPE
,FAPI_JWT_SECRET_KEY
). -
Create
config/.secrets.toml
by copyingconfig/.secrets.toml.example
. Add yourJWT_SECRET_KEY
(must be strong and secret). Do not commit.secrets.toml
.# config/.secrets.toml [default] JWT_SECRET_KEY="your_super_secret_strong_key_here_min_32_chars" # Optional: Add sensitive DB credentials if not using env vars # SQL_DATABASE_URL="postgresql+asyncpg://user:pass@host:port/dbname" # MONGO_DATABASE_URL="mongodb://user:pass@host:port/"
-
Edit
config/settings.toml
to select your database backend:- Set
database_type
to"sqlite"
,"postgres"
, or"mongodb"
. - Ensure the corresponding database URL (
sql_database_url
ormongo_database_url
) is correctly set (either here, in.secrets.toml
, or via environment variables likeFAPI_SQL_DATABASE_URL
). The default usestest.db
. - If using MongoDB, set
mongo_db_name
.
- Set
-
-
Initialize Database:
- SQL (SQLite/PostgreSQL): This project includes
alembic
as a dependency for potential migrations.- Ensure your database exists.
- If you have Alembic migrations set up (e.g.,
alembic.ini
file and amigrations/
directory), run:alembic upgrade head
- (If Alembic is not fully configured, you may need to initialize it or manage schema changes manually)
- MongoDB: Ensure your MongoDB server is running. The application will automatically attempt to create the required unique indexes for the
users
collection (onusername
andemail
) when it starts up, using the database name specified bymongo_db_name
in your settings.
- SQL (SQLite/PostgreSQL): This project includes
uvicorn main:app --reload --host 0.0.0.0 --port 8000
The API will be available at http://localhost:8000
.
Ensure test dependencies are installed (uv pip install -e '.[test]'
).
Using the helper script:
chmod +x run_tests.sh
./run_tests.sh
This script provides options for different test runs (verbose, coverage, etc.).
Using pytest directly:
# Run all tests (verbose)
PYTHONPATH=. pytest -v
# Run tests with coverage report
PYTHONPATH=. pytest --cov=app --cov-report=term-missing --cov-report=html
Coverage report will be in the htmlcov/
directory.
If you have act
installed, you can simulate GitHub Actions workflows locally. This is particularly useful for testing CI/CD pipelines before pushing changes.
# Run workflows, specifying architecture if needed (e.g., for M1/M2 Macs)
act --container-architecture linux/amd64
Once the server is running, access the interactive API documentation:
- Swagger UI:
http://localhost:8000/docs
- ReDoc:
http://localhost:8000/redoc
- Stop the application.
- Update
config/settings.toml
or environment variables:- Change
database_type
. - Ensure the correct URL (
sql_database_url
ormongo_database_url
) is set. - Update
mongo_db_name
if switching to MongoDB.
- Change
- Ensure the target database server (PostgreSQL or MongoDB) is running and accessible.
- If switching to SQL, ensure the database exists and migrations are applied (
alembic upgrade head
). - If switching to MongoDB, ensure indexes exist.
- Restart the application:
uvicorn main:app --reload ...