Tu apprends Python et tu veux construire des applications web modernes ? L’un des frameworks les plus puissants et les plus agrĂ©ables Ă utiliser est FastAPI. Contrairement Ă Flask (minimaliste) ou Django (monolithique), FastAPI se positionne comme le choix idĂ©al pour les APIs REST, les microservices et les applications temps rĂ©el â le tout avec des performances dignes de Node.js ou Go.
Dans ce tutoriel pas-à -pas, tu vas construire une API REST complÚte de gestion de tùches (Todo API) avec FastAPI, en découvrant les concepts clés : validation automatique, documentation interactive, base de données SQLite et déploiement.
Pourquoi FastAPI plutĂŽt que Flask ou Django ?
Avant de coder, voici pourquoi FastAPI a conquis la communauté Python :
- Performances : Basé sur Starlette (asynchrone natif), FastAPI rivalise avec Go et Node.js en termes de débit.
- Validation automatique : Avec Pydantic, tu déclares tes modÚles de données et FastAPI valide, sérialise et documente tout automatiquement.
- Documentation interactive : Swagger UI et ReDoc sont gĂ©nĂ©rĂ©s automatiquement Ă partir de ton code â plus besoin de maintenir une doc sĂ©parĂ©e.
- Async natif :
async/awaitest supportĂ© nativement, idĂ©al pour les appels API externes, les bases de donnĂ©es et le temps rĂ©el. - Type hints : FastAPI exploite les type hints Python â ton IDE te suggĂšre le code, et la validation est garantie Ă l’exĂ©cution.
1. Installation et configuration
Crée un environnement virtuel et installe FastAPI avec un serveur ASGI :
python -m venv venv
source venv/bin/activate # ou venv\Scripts\activate sur Windows
pip install fastapi uvicornC’est tout ce dont tu as besoin pour commencer. Uvicorn est le serveur ASGI haute performance qui exĂ©cutera ton application.
2. Ta premiĂšre API en 10 lignes
Crée un fichier main.py :
from fastapi import FastAPI
app = FastAPI(title="Todo API", version="1.0.0")
@app.get("/")
def read_root():
return {"message": "Bienvenue sur la Todo API !"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "query": q}Lance le serveur :
uvicorn main:app --reloadOuvre http://127.0.0.1:8000 dans ton navigateur. Tu vois {"message": "Bienvenue sur la Todo API !"}. Maintenant, visite http://127.0.0.1:8000/docs â tu as dĂ©jĂ une documentation Swagger interactive, gĂ©nĂ©rĂ©e automatiquement Ă partir de ton code !
Remarque la magie des type hints : FastAPI sait que item_id est un entier (il valide et convertit automatiquement) et que q est une chaßne optionnelle. Pas de boilerplate de validation à écrire !
3. Les modĂšles Pydantic â Le cĆur de FastAPI
Les modÚles Pydantic définissent la structure de tes données et assurent la validation automatique. Ajoute ceci dans main.py :
from pydantic import BaseModel
from datetime import datetime
from typing import Optional
class TodoCreate(BaseModel):
title: str
description: Optional[str] = None
completed: bool = False
class Todo(TodoCreate):
id: int
created_at: datetime
Maintenant, utilisons-les dans une route POST :
todos: list[Todo] = []
next_id = 1
@app.post("/todos/", response_model=Todo)
def create_todo(todo: TodoCreate):
global next_id
new_todo = Todo(
id=next_id,
title=todo.title,
description=todo.description,
completed=todo.completed,
created_at=datetime.now()
)
todos.append(new_todo)
next_id += 1
return new_todoTeste avec la doc Swagger : envoie un JSON {"title": "Apprendre FastAPI"} et reçois une tĂąche créée avec un ID et une date automatiques. Envoie un {"title": ""} â FastAPI le rejette automatiquement avec un message d’erreur clair (car une chaĂźne vide n’est pas un titre valide par dĂ©faut).
4. Route complĂšte CRUD
Ajoutons la récupération de toutes les tùches et la suppression :
@app.get("/todos/", response_model=list[Todo])
def list_todos(skip: int = 0, limit: int = 10):
return todos[skip : skip + limit]
@app.get("/todos/{todo_id}", response_model=Todo)
def get_todo(todo_id: int):
for todo in todos:
if todo.id == todo_id:
return todo
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="TĂąche introuvable")
@app.delete("/todos/{todo_id}")
def delete_todo(todo_id: int):
for i, todo in enumerate(todos):
if todo.id == todo_id:
todos.pop(i)
return {"message": "Tùche supprimée"}
raise HTTPException(status_code=404, detail="TĂąche introuvable")Observe comme les paramĂštres de requĂȘte (skip, limit) sont automatiquement parsĂ©s depuis l’URL. FastAPI distingue tout seul les paramĂštres de path, de query et de body â pas besoin de dĂ©corateurs supplĂ©mentaires.
5. Persistance avec SQLite et SQLAlchemy
Pour l’instant, nos donnĂ©es sont en mĂ©moire et disparaissent au redĂ©marrage. Ajoutons une vraie base de donnĂ©es :
pip install sqlalchemy aiosqliteCrée un fichier database.py :
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, DeclarativeBase
SQLALCHEMY_DATABASE_URL = "sqlite:///./todos.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
class Base(DeclarativeBase):
passEt un modĂšle SQLAlchemy dans models.py :
from sqlalchemy import Column, Integer, String, Boolean, DateTime
from database import Base
from datetime import datetime
class TodoDB(Base):
__tablename__ = "todos"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, nullable=False)
description = Column(String, nullable=True)
completed = Column(Boolean, default=False)
created_at = Column(DateTime, default=datetime.now)Pour utiliser la base de données dans FastAPI, on ajoute une dépendance :
# Dans main.py
from database import SessionLocal, engine
from models import TodoDB
import models
models.Base.metadata.create_all(bind=engine)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/todos/", response_model=Todo)
def create_todo(todo: TodoCreate, db: Session = Depends(get_db)):
db_todo = TodoDB(title=todo.title, description=todo.description)
db.add(db_todo)
db.commit()
db.refresh(db_todo)
return Todo(id=db_todo.id, title=db_todo.title,
description=db_todo.description,
completed=db_todo.completed,
created_at=db_todo.created_at)6. Tests automatiques
FastAPI s’intĂšgre parfaitement avec Pytest. Le client de test TestClient te permet de tester ton API sans serveur HTTP :
pip install pytest httpx# test_main.py
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Bienvenue sur la Todo API !"}
def test_create_todo():
response = client.post("/todos/", json={"title": "Tester FastAPI"})
assert response.status_code == 200
data = response.json()
assert data["title"] == "Tester FastAPI"
assert "id" in data
assert data["completed"] is FalseExĂ©cute pytest â les tests passent en une fraction de seconde. Ce pattern de test intĂ©grĂ© est l’un des grands avantages de FastAPI pour le dĂ©veloppement professionnel.
Ce que tu as appris
- â Installer et configurer FastAPI avec Uvicorn
- â CrĂ©er des routes REST avec paramĂštres validĂ©s automatiquement
- â DĂ©finir des modĂšles Pydantic pour la validation des donnĂ©es
- â Construire une API CRUD complĂšte
- â Connecter SQLite via SQLAlchemy pour la persistance
- â Tester ton API avec Pytest et TestClient
FastAPI n’est pas seulement rapide â il rend le dĂ©veloppement d’APIs plus sĂ»r et plus agrĂ©able. La validation automatique avec Pydantic, la documentation gĂ©nĂ©rĂ©e et le typage strict rĂ©duisent les bugs et accĂ©lĂšrent le dĂ©veloppement.
Envie d’aller plus loin ? Tu peux ajouter l’authentification JWT, la pagination avancĂ©e, ou dĂ©ployer ton API avec Docker sur un VPS. Chacun de ces sujets mĂ©rite un article dĂ©diĂ© !
đ Tu dĂ©butes en Python et tu veux maĂźtriser les fondamentaux avant de te lancer dans les APIs ? Le cours Python â Les Fondamentaux t’enseigne tout ce qu’il faut savoir : variables, fonctions, listes, dictionnaires, classes et modules â les bases solides dont tu as besoin pour construire des projets comme cette API REST.