DEV Community

Cover image for Structuring a FastAPI Project: Best Practices
Mohammad
Mohammad

Posted on

1

Structuring a FastAPI Project: Best Practices

FastAPI is a powerful and efficient web framework for building APIs with Python. However, as projects grow, organizing the code properly becomes crucial for maintainability and scalability. This article outlines a structured approach to organizing FastAPI projects, inspired by the official documentation and best practices.

Recommended FastAPI Project Structure

A well-structured FastAPI project should separate concerns into different modules, ensuring clear boundaries between routing, models, schemas, services, and database interactions. Below is a directory structure that works well for most projects:

my_fastapi_project/
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── dependencies.py
│   ├── routers/
│   │   ├── __init__.py
│   │   ├── users.py
│   │   └── items.py
│   ├── internal/
│   │   ├── __init__.py
│   │   └── admin.py
│   ├── core/
│   │   ├── __init__.py
│   │   ├── config.py
│   │   └── security.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── user.py
│   │   └── item.py
│   ├── schemas/
│   │   ├── __init__.py
│   │   ├── user.py
│   │   └── item.py
│   ├── services/
│   │   ├── __init__.py
│   │   ├── user_service.py
│   │   └── item_service.py
│   └── db/
│       ├── __init__.py
│       ├── database.py
│       └── migrations/
├── tests/
│   ├── __init__.py
│   ├── test_main.py
│   ├── test_users.py
│   ├── test_items.py
├── .env
├── .gitignore
├── requirements.txt
├── README.md
└── run.sh
Enter fullscreen mode Exit fullscreen mode

Explanation of the Structure with Examples

1. Main Application (app/)

  • main.py: The entry point of the FastAPI application.
  from fastapi import FastAPI
  from app.routers import users, items

  app = FastAPI()

  app.include_router(users.router)
  app.include_router(items.router)
Enter fullscreen mode Exit fullscreen mode
  • dependencies.py: Contains shared dependencies like database sessions.
  from sqlalchemy.orm import Session
  from app.db.database import SessionLocal

  def get_db():
      db = SessionLocal()
      try:
          yield db
      finally:
          db.close()
Enter fullscreen mode Exit fullscreen mode

2. Routers (app/routers/)

Handles API endpoints:

  • users.py:
  from fastapi import APIRouter, Depends
  from sqlalchemy.orm import Session
  from app.schemas.user import UserCreate
  from app.services.user_service import create_user
  from app.dependencies import get_db

  router = APIRouter(prefix="/users", tags=["users"])

  @router.post("/", response_model=UserCreate)
  def create_new_user(user: UserCreate, db: Session = Depends(get_db)):
      return create_user(db, user)
Enter fullscreen mode Exit fullscreen mode

3. Internal (app/internal/)

Contains internal, non-public endpoints, such as an admin panel.

  • admin.py:
  from fastapi import APIRouter

  router = APIRouter(prefix="/admin", tags=["admin"])

  @router.get("/dashboard")
  def get_admin_dashboard():
      return {"message": "Admin Dashboard"}
Enter fullscreen mode Exit fullscreen mode

4. Core (app/core/)

Holds configurations and security settings:

  • config.py:
  import os
  from dotenv import load_dotenv

  load_dotenv()

  DATABASE_URL = os.getenv("DATABASE_URL")
  SECRET_KEY = os.getenv("SECRET_KEY")
Enter fullscreen mode Exit fullscreen mode
  • security.py:
  from passlib.context import CryptContext

  pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

  def hash_password(password: str):
      return pwd_context.hash(password)
Enter fullscreen mode Exit fullscreen mode

5. Models (app/models/)

Defines SQLAlchemy models:

  • user.py:
  from sqlalchemy import Column, Integer, String
  from app.db.database import Base

  class User(Base):
      __tablename__ = "users"
      id = Column(Integer, primary_key=True, index=True)
      username = Column(String, unique=True, index=True)
      password_hash = Column(String)
Enter fullscreen mode Exit fullscreen mode

6. Schemas (app/schemas/)

Pydantic models for data validation:

  • user.py:
  from pydantic import BaseModel

  class UserCreate(BaseModel):
      username: str
      password: str
Enter fullscreen mode Exit fullscreen mode

7. Services (app/services/)

Contains business logic separate from API routes:

  • user_service.py:
  from sqlalchemy.orm import Session
  from app.models.user import User
  from app.schemas.user import UserCreate
  from app.core.security import hash_password

  def create_user(db: Session, user: UserCreate):
      db_user = User(username=user.username, password_hash=hash_password(user.password))
      db.add(db_user)
      db.commit()
      db.refresh(db_user)
      return db_user
Enter fullscreen mode Exit fullscreen mode

8. Database (app/db/)

  • database.py:
  from sqlalchemy import create_engine
  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy.orm import sessionmaker
  from app.core.config import DATABASE_URL

  engine = create_engine(DATABASE_URL)
  SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
  Base = declarative_base()
Enter fullscreen mode Exit fullscreen mode

9. Tests (tests/)

Includes unit and integration tests:

  • test_users.py:
  def test_create_user():
      response = client.post("/users/", json={"username": "testuser", "password": "testpass"})
      assert response.status_code == 200
      assert response.json()["username"] == "testuser"
Enter fullscreen mode Exit fullscreen mode

Conclusion

By structuring your FastAPI project properly, you ensure better scalability, maintainability, and testability. Following this structure allows developers to collaborate efficiently and keep the code clean and organized.

💬What is your opinion?
Do you think a different structure would work better?

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay