Ces dernières années, une véritable révolution s'est produite dans le monde du développement Python. De plus en plus d'équipes choisissent FastAPI pour leurs nouveaux projets, remplaçant progressivement Django, le framework qui a été la norme de l'industrie pendant de nombreuses années. Voyons ce qui se passe et pourquoi les développeurs débutants devraient prêter attention à FastAPI.
Que sont FastAPI et Django ?
Django est un framework Web complet qui existe depuis 2005. Il a été créé pour développer des applications Web à part entière avec un panneau d'administration intégré, ORM, un système de modèles et de nombreuses autres fonctionnalités « prêtes à l'emploi ».
FastAPI — un framework moderne apparu en 2018, spécialement conçu pour le développement d'API. Il est construit sur les capacités modernes de Python 3.7+ et la programmation asynchrone.
Pourquoi FastAPI gagne en popularité ?
1. Performances comme Go et Node.js
FastAPI est l'un des frameworks Python les plus rapides grâce à l'asynchronisme. Voici une comparaison simple :
# Django (approche synchrone)
from django.http import JsonResponse
def get_users(request):
users = User.objects.all() # Requête de blocage
return JsonResponse({'users': list(users.values())})# FastAPI (approche asynchrone)
from fastapi import FastAPI
from typing import List
app = FastAPI()
@app.get("/users")
async def get_users() -> List[dict]:
users = await database.fetch_all("SELECT * FROM users")
return users💡 Important : Dans FastAPI, les requêtes sont traitées de manière asynchrone, ce qui permet au serveur de gérer des milliers de connexions simultanément sans blocage. Django prend également en charge l'asynchronisme depuis la version 3.1, mais l'écosystème n'est pas encore entièrement adapté.
2. Démarrage incroyablement facile
Vous pouvez créer la première API dans FastAPI en seulement 5 minutes :
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello, world!"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}Lancer avec la commande :
uvicorn main:app --reload✅ Et voilà ! Vous avez déjà une API fonctionnelle. Pas de paramètres, de fichiers de configuration ou de structures de projet complexes.
3. La documentation automatique, c'est magique
L'une des fonctionnalités les plus cool de FastAPI est la documentation interactive automatique. Il suffit d'ouvrir http://localhost:8000/docs, et vous verrez la documentation complète de l'interface utilisateur Swagger, où vous pouvez tester chaque point de terminaison directement dans le navigateur.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(
title="My project's API",
description="Description of all endpoints",
version="1.0.0"
)
class Item(BaseModel):
name: str
description: str = None
price: float
@app.post("/items/")
async def create_item(item: Item):
"""
Creating a new product:
- **name**: product name
- **description**: description (optional)
- **price**: product price
"""
return {"item": item}La documentation est générée automatiquement à partir des types de données et des chaînes de documentation. Dans Django, pour cela, vous devez utiliser des bibliothèques supplémentaires telles que drf-spectacular.
4. Typage et validation de la boîte
FastAPI utilise Pydantic pour la validation automatique des données :
from pydantic import BaseModel, EmailStr, validator
from typing import Optional
class User(BaseModel):
username: str
email: EmailStr
age: Optional[int] = None
@validator('age')
def age_must_be_positive(cls, v):
if v is not None and v < 0:
raise ValueError('Age cannot be negative')
return v
@app.post("/users/")
async def create_user(user: User):
# Si les données ne sont pas valides, FastAPI renverra automatiquement une erreur 422
# avec une description détaillée du problème
return {"user": user}Si vous envoyez des données non valides, vous recevrez une erreur claire indiquant tous les problèmes.
5. Travail moderne avec les dépendances
Dependency Injection dans FastAPI rend le code propre et testable :
from fastapi import Depends, HTTPException
from sqlalchemy.orm import Session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
def get_current_user(token: str = Header(...)):
user = verify_token(token)
if not user:
raise HTTPException(status_code=401, detail="Unauthorized")
return user
@app.get("/users/me")
async def read_current_user(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
return current_userLes dépendances sont automatiquement résolues et implémentées. Cela rend les tests incroyablement faciles.
6. WebSocket et tâches en arrière-plan
from fastapi import WebSocket, BackgroundTasks
import time
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Received: {data}")
def write_log(message: str):
time.sleep(5) # Longue opération
with open("log.txt", "a") as f:
f.write(message)
@app.post("/send-notification/")
async def send_notification(
email: str,
background_tasks: BackgroundTasks
):
background_tasks.add_task(write_log, f"Sent to {email}")
return {"message": "Notification will be sent"}
Quand choisir Django ?
FastAPI n'est pas toujours le meilleur choix. Django est préférable si vous avez besoin de :
Application Web complète avec panneau d'administration — Django Admin prêt à l'emploi
Système d'authentification et d'autorisation — prête et éprouvée
ORM avec migrations — Django ORM est plus facile pour les débutants
Système de modèles intégré — si vous avez besoin de server-side rendering
Un vaste écosystème de paquets — Django existe depuis 19 ans
Exemple pratique : API CRUD
Créons une API CRUD simple pour gérer les tâches :
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
from datetime import datetime
app = FastAPI()
class Task(BaseModel):
id: Optional[int] = None
title: str
description: Optional[str] = None
completed: bool = False
created_at: Optional[datetime] = None
# Stockage temporaire (en réalité, utilisez la base de données)
tasks_db = []
task_id_counter = 1
@app.post("/tasks/", response_model=Task)
async def create_task(task: Task):
global task_id_counter
task.id = task_id_counter
task.created_at = datetime.now()
task_id_counter += 1
tasks_db.append(task)
return task
@app.get("/tasks/", response_model=List[Task])
async def get_tasks(completed: Optional[bool] = None):
if completed is None:
return tasks_db
return [t for t in tasks_db if t.completed == completed]
@app.get("/tasks/{task_id}", response_model=Task)
async def get_task(task_id: int):
task = next((t for t in tasks_db if t.id == task_id), None)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
return task
@app.put("/tasks/{task_id}", response_model=Task)
async def update_task(task_id: int, task_update: Task):
task = next((t for t in tasks_db if t.id == task_id), None)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
task.title = task_update.title
task.description = task_update.description
task.completed = task_update.completed
return task
@app.delete("/tasks/{task_id}")
async def delete_task(task_id: int):
global tasks_db
tasks_db = [t for t in tasks_db if t.id != task_id]
return {"message": "Task deleted"}Intégration avec la base de données
FastAPI fonctionne très bien avec SQLAlchemy :
from sqlalchemy import create_engine, Column, Integer, String, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./tasks.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class TaskModel(Base):
__tablename__ = "tasks"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
description = Column(String)
completed = Column(Boolean, default=False)
Base.metadata.create_all(bind=engine)
@app.post("/tasks/", response_model=Task)
async def create_task(task: Task, db: Session = Depends(get_db)):
db_task = TaskModel(**task.dict(exclude={'id'}))
db.add(db_task)
db.commit()
db.refresh(db_task)
return db_taskAuthentification et sécurité
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from passlib.context import CryptContext
from jose import JWTError, jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=30)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials"
)
access_token = create_access_token(data={"sub": user.username})
return {"access_token": access_token, "token_type": "bearer"}
async def get_current_user(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(status_code=401)
return username
except JWTError:
raise HTTPException(status_code=401)
@app.get("/users/me")
async def read_users_me(current_user: str = Depends(get_current_user)):
return {"username": current_user}Test
FastAPI simplifie les tests :
from fastapi.testclient import TestClient
client = TestClient(app)
def test_create_task():
response = client.post(
"/tasks/",
json={"title": "Test task", "description": "Description"}
)
assert response.status_code == 200
assert response.json()["title"] == "Test task"
def test_get_tasks():
response = client.get("/tasks/")
assert response.status_code == 200
assert isinstance(response.json(), list)Performance : faits et chiffres
Selon TechEmpower Benchmarks (2026) :
Cadre | Requêtes par seconde | Productivité |
|---|---|---|
FastAPI | ~60,000 | ⭐⭐⭐⭐⭐ |
Django Ninja | ~40,000 | ⭐⭐⭐⭐ |
Django + gunicorn | ~10,000 | ⭐⭐⭐ |
🚀 Conclusion : FastAPI peut traiter 6 fois plus de requêtes avec la même charge !
Dans Codique vous trouverez des cours détaillés sur Python, FastAPI, Django et d'autres technologies modernes. Nous enseignons la programmation en pratique, avec des projets réels et des explications claires.
🚀 Rejoignez notre canal Telegram — vous trouverez ici une communauté amicale de développeurs, des ressources utiles, des analyses de code et des réponses à vos questions. Nous vous aiderons à devenir un spécialiste recherché !
Commencez votre parcours de programmation avec Kodik : apprenez de manière pratique, rapide et efficace !
