FastAPI Day 8: Designing a Scalable Project Structure Using the Official Template
The article explains why a FastAPI backend should move from a single main.py file to a responsibility‑layered architecture, detailing the recommended directory layout, pydantic‑settings configuration, SQLModel SQLite integration, APIRouter modular routing, and the resulting test coverage.
From a single main.py that "runs the world" to a responsibility‑layered design, the FastAPI project structure should be planned early to avoid maintenance headaches.
Why a structure is needed
A complete FastAPI backend eventually includes:
Data models
Routes (users, items, auth, admin…)
Database operations
Authentication & authorization
Configuration files
Tests
Putting everything into main.py works but becomes hard to maintain. The official full-stack-fastapi-template provides a reference layout, which this 14‑day series adapts.
Project directory layout
fastapi-14days/
├── main.py # application entry point
├── models.py # all data models
├── core/
│ ├── config.py # configuration (environment variables)
│ ├── db.py # database engine and session
│ └── security.py # JWT + password hashing
├── api/
│ ├── deps.py # common dependencies (SessionDep, CurrentUser)
│ └── routes/
│ ├── auth.py # authentication routes
│ └── todos.py # Todo CRUD routes
└── tests/
├── conftest.py # test configuration
└── ...Core idea: layer by responsibility, not by technology. core/ holds infrastructure unrelated to business logic, api/ contains routes and dependencies, and models.py stores all data models for quick overview.
Configuration management with pydantic‑settings
Configuration values are placed in a .env file:
DATABASE_URL=sqlite:///./fastapi14days.db
SECRET_KEY=change-this-in-production
ACCESS_TOKEN_EXPIRE_MINUTES=30They are loaded via pydantic-settings:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
DATABASE_URL: str = "sqlite:///./fastapi14days.db"
SECRET_KEY: str
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
settings = Settings()In production you only replace the .env file; no code changes are required.
Database integration: SQLModel + SQLite
SQLModelcombines SQLAlchemy and Pydantic, allowing a single definition for database tables and data validation:
from sqlmodel import SQLModel, Field
from typing import Optional
class User(SQLModel, table=True):
__tablename__ = "users"
id: Optional[int] = Field(default=None, primary_key=True)
email: str = Field(unique=True, index=True)
hashed_password: str
full_name: Optional[str] = NoneAfter defining models, SQLModel.metadata.create_all(engine) automatically creates the tables.
Modular routing with APIRouter
Each functional module gets its own router:
from fastapi import APIRouter
router = APIRouter(prefix="/todos", tags=["todos"])
@router.post("", status_code=201)
def create_todo(...):
...The main application includes the routers:
from api.routes.auth import router as auth_router
from api.routes.todos import router as todos_router
app.include_router(auth_router)
app.include_router(todos_router)Adding new functionality only requires a new router file; main.py remains unchanged.
What was done on Day 8
Built a complete layered project structure (core/api/models)
Integrated database with SQLModel + SQLite
Managed configuration using pydantic‑settings
Modularized routes with APIRouter
Refactored auth and todos routes into separate files
All 47 tests continue to pass
Next steps
Days 9‑12 will combine the learned pieces into a full Todo API project that can be run end‑to‑end.
Related links
Official FastAPI documentation (Chinese):
https://fastapi.tiangolo.com/zh/tutorial/sql-databases/
https://fastapi.tiangolo.com/zh/tutorial/bigger-applications/Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tech Ocean
Focused on AI programming, sharing ready-to-use development efficiency solutions.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
