Skip to content

Base project for FastAPI-based APIs implementing clean architecture patterns for maintainable and testable code.

License

Notifications You must be signed in to change notification settings

daireto/base-clean-arch-fastapi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Base Clean Architecture FastAPI-based API

This is a base project for FastAPI-based APIs implementing clean architecture patterns for maintainable and testable code.

Feel free to use it as a starting point for your own projects.

πŸ—οΈ Architecture

This project follows the Clean Architecture pattern, with the following layers:

  • Domain Layer: Core business logic and entities.
  • Application Layer: Use cases and application services.
  • Infrastructure Layer: External dependencies and integrations.

The project is structured around modules (vertical slices), with each module having its own directory containing all the necessary layers.

It also implements other patterns and practices, such as:

  • Builder Pattern for entity creation.
  • Dependency Injection (via Lagom).
  • Data Transfer Objects (DTOs) for request and response payloads.
  • Value Objects for data validation.
  • Result Pattern for handling operation outcomes.
  • Repository Pattern for data access.
  • Collections for enhanced filtering and sorting.
  • Instrumentation for logging and monitoring use cases.
  • OData V4 Query for filtering and sorting data.
  • Correlation ID for request tracing.

πŸš€ Technology Stack

These are some of the main technologies used in this project:

  • FastAPI - Web framework for building APIs.
  • SQLActive - ActiveRecord pattern for database operations.
  • SQLite - Database (via aiosqlite for async operations).
  • Lagom - Dependency injection container.
  • Pydantic - Data validation and settings management.
  • Orjson - Fast JSON serialization.
  • Uvloop - High-performance event loop.
  • Structlog - Structured logging.
  • Validators - Data validation.
  • OData V4 Query - OData query parsing.
  • ASGI Correlation ID - Requests correlation with unique IDs.
  • Ruff - Linter and code formatter.
  • Pytest - Testing framework.

πŸ“ Project Structure

.
β”œβ”€β”€ .env.example                # Environment variables template
β”œβ”€β”€ api.http                    # HTTP requests for testing
β”œβ”€β”€ COMMITS.md                  # Git commit guidelines
β”œβ”€β”€ pyproject.toml              # Project configuration and dependencies
β”œβ”€β”€ README.md                   # Project documentation
β”œβ”€β”€ ruff.toml                   # Ruff linter configuration
β”œβ”€β”€ uv.lock                     # UV dependency lock file
β”œβ”€β”€ LICENSE.md                  # Project license
β”œβ”€β”€ src/                        # Source code
β”‚   β”œβ”€β”€ main.py                 # FastAPI application entry point
β”‚   β”œβ”€β”€ config.py               # Application configuration
β”‚   β”œβ”€β”€ health.py               # Health check logic
β”‚   β”œβ”€β”€ logger.py               # Logging configuration
β”‚   β”œβ”€β”€ middlewares/            # Application middlewares
β”‚   β”‚   └── access_log_middleware.py # Access logging middleware
β”‚   β”œβ”€β”€ modules/                # Feature modules (domain-driven)
β”‚   β”‚   └── resources/          # Resources feature module
β”‚   β”‚       β”œβ”€β”€ application/    # Application layer (use cases)
β”‚   β”‚       β”‚   └── use_cases/  # Use case implementations
β”‚   β”‚       β”‚       β”œβ”€β”€ create_resource.py
β”‚   β”‚       β”‚       β”œβ”€β”€ delete_resource.py
β”‚   β”‚       β”‚       β”œβ”€β”€ get_resource.py
β”‚   β”‚       β”‚       β”œβ”€β”€ list_resources.py
β”‚   β”‚       β”‚       └── update_resource.py
β”‚   β”‚       β”œβ”€β”€ domain/         # Domain layer
β”‚   β”‚       β”‚   β”œβ”€β”€ entities.py         # Domain entities
β”‚   β”‚       β”‚   β”œβ”€β”€ error_codes.py      # Domain-specific error codes
β”‚   β”‚       β”‚   β”œβ”€β”€ exceptions.py       # Domain-specific exceptions
β”‚   β”‚       β”‚   β”œβ”€β”€ value_objects.py    # Value objects
β”‚   β”‚       β”‚   β”œβ”€β”€ collections.py      # Domain collections
β”‚   β”‚       β”‚   └── interfaces/         # Repository interfaces
β”‚   β”‚       β”‚       └── repositories.py
β”‚   β”‚       β”œβ”€β”€ infrastructure/ # Infrastructure layer
β”‚   β”‚       β”‚   β”œβ”€β”€ instrumentation/ # Use case instrumentation/decorators
β”‚   β”‚       β”‚   β”‚   └── use_cases/
β”‚   β”‚       β”‚   β”‚       β”œβ”€β”€ create_resource.py
β”‚   β”‚       β”‚   β”‚       β”œβ”€β”€ delete_resource.py
β”‚   β”‚       β”‚   β”‚       β”œβ”€β”€ get_resource.py
β”‚   β”‚       β”‚   β”‚       β”œβ”€β”€ list_resources.py
β”‚   β”‚       β”‚   β”‚       └── update_resource.py
β”‚   β”‚       β”‚   └── persistence/ # Persistence implementations
β”‚   β”‚       β”‚       β”œβ”€β”€ models/         # Database models
β”‚   β”‚       β”‚       β”‚   β”œβ”€β”€ mock.py     # Mock models for testing
β”‚   β”‚       β”‚       β”‚   └── sqlite.py   # SQLite database models
β”‚   β”‚       β”‚       └── repositories/   # Repository implementations
β”‚   β”‚       β”‚           β”œβ”€β”€ mock.py     # Mock repository for testing
β”‚   β”‚       β”‚           └── sqlite.py   # SQLite repository implementation
β”‚   β”‚       β”œβ”€β”€ presentation/   # Presentation layer (API)
β”‚   β”‚       β”‚   β”œβ”€β”€ api.py      # Resource API endpoints
β”‚   β”‚       β”‚   └── dtos.py     # Data transfer objects
β”‚   β”‚       └── di.py           # Dependency injection configuration
β”‚   └── shared/                 # Shared utilities and common code
β”‚       β”œβ”€β”€ application/        # Shared application layer
β”‚       β”‚   └── interfaces/     # Shared interfaces
β”‚       β”‚       β”œβ”€β”€ base.py     # Base interfaces
β”‚       β”‚       └── instrumentation.py # Instrumentation interfaces
β”‚       β”œβ”€β”€ domain/             # Shared domain layer
β”‚       β”‚   β”œβ”€β”€ entity.py       # Entity base class
β”‚       β”‚   β”œβ”€β”€ error_codes.py  # Shared error codes
β”‚       β”‚   β”œβ”€β”€ exceptions.py   # Shared exception classes
β”‚       β”‚   β”œβ”€β”€ value_object.py # Value object base class
β”‚       β”‚   └── helpers/        # Domain helpers
β”‚       β”‚       └── odata_helper.py # OData query helper
β”‚       β”œβ”€β”€ infrastructure/     # Shared infrastructure
β”‚       β”‚   β”œβ”€β”€ db.py           # Database connection utilities
β”‚       β”‚   └── persistence/    # Shared persistence
β”‚       β”‚       β”œβ”€β”€ models/     # Shared models
β”‚       β”‚       └── repositories/ # Shared repositories
β”‚       β”œβ”€β”€ presentation/       # Shared presentation layer
β”‚       β”‚   β”œβ”€β”€ api.py          # Shared API routes (e.g., health check)
β”‚       β”‚   β”œβ”€β”€ dtos.py         # Base DTO classes
β”‚       β”‚   └── responses.py    # Response utilities
β”‚       └── utils/              # Shared utility functions
β”‚           └── uuid_tools.py   # UUID utility functions
β”œβ”€β”€ tests/                      # Tests directory
β”‚   β”œβ”€β”€ conftest.py            # Pytest global fixtures
β”‚   β”œβ”€β”€ resources/             # Resource module tests
β”‚   β”‚   β”œβ”€β”€ application/       # Application layer tests
β”‚   β”‚   β”‚   β”œβ”€β”€ test_create_resource.py
β”‚   β”‚   β”‚   β”œβ”€β”€ test_delete_resource.py
β”‚   β”‚   β”‚   β”œβ”€β”€ test_get_resource.py
β”‚   β”‚   β”‚   β”œβ”€β”€ test_list_resources.py
β”‚   β”‚   β”‚   └── test_update_resource.py
β”‚   β”‚   β”œβ”€β”€ domain/            # Domain layer tests
β”‚   β”‚   β”‚   β”œβ”€β”€ conftest.py
β”‚   β”‚   β”‚   └── test_collections.py
β”‚   β”‚   β”œβ”€β”€ infrastructure/    # Infrastructure layer tests
β”‚   β”‚   β”‚   └── persistence/   # Persistence layer tests
β”‚   β”‚   β”‚       └── repositories/ # Repository tests
β”‚   β”‚   β”‚           └── test_sqlite_resource_repository.py
β”‚   β”‚   └── presentation/      # Presentation layer tests
β”‚   β”‚       β”œβ”€β”€ test_create_resource.py
β”‚   β”‚       β”œβ”€β”€ test_delete_resource.py
β”‚   β”‚       β”œβ”€β”€ test_get_resource.py
β”‚   β”‚       β”œβ”€β”€ test_list_resources.py
β”‚   β”‚       └── test_update_resource.py
β”‚   └── shared/                # Shared tests
β”‚       └── presentation/      # Shared presentation tests
β”‚           └── api/           # API tests
β”‚               └── test_health.py # Health endpoint tests

πŸ› οΈ Development Setup

Prerequisites

  • Python 3.10+
  • uv

Installation

  1. Clone the repository
  2. Create and activate a virtual environment:
    uv venv .venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
  3. Install dependencies:
    uv sync

Running the Application

Run the application with:

uv run main.py

The API will be available at http://127.0.0.1:$PORT/. Replace $PORT with the port number you configured in the .env file (see the configuration section below).

πŸ”§ Configuration

Copy the .env.example file to .env and update the settings as needed.

cp .env.example .env

Example .env file:

ENV=dev
PORT=8000
DEBUG=True
DATABASE_URL=sqlite+aiosqlite:///./test.db
MAX_RECORDS_PER_PAGE=100
LOGS_PATH=./.logs/app.log

Database

  • Development: SQLite database.
  • Connection: Configured via DATABASE_URL setting.
  • Migrations: Automatic table creation on startup.

πŸ“š API Documentation

  • Swagger UI: http://127.0.0.1:$PORT/docs
  • ReDoc: http://127.0.0.1:$PORT/redoc

Replace $PORT with the port number you configured in the .env file.

πŸ§ͺ Testing & Linting

Run tests with pytest:

uv run -m pytest

Run linting with ruff:

uv run -m ruff check .

πŸ“‹ Available Endpoints

Health Check

  • GET /health - Application health status.
  • GET /ping - Same as /health.

Resources

  • Resource endpoints are available under the /resources prefix.

πŸ›οΈ Clean Architecture Benefits

This project structure provides:

  • Testability: Easy to unit test business logic.
  • Maintainability: Clear separation of concerns.
  • Flexibility: Easy to swap implementations (e.g., database providers).
  • Independence: Domain logic independent of frameworks.

🀝 Contributing

  1. Check the commits guidelines.
  2. Follow the existing architecture patterns.
  3. Add tests for new functionality.
  4. Use type hints throughout.
  5. Run linting with ruff before committing.

πŸ“„ License

This project is licensed under the MIT License.

About

Base project for FastAPI-based APIs implementing clean architecture patterns for maintainable and testable code.

Topics

Resources

License

Stars

Watchers

Forks

Languages