technova-api / app /database.py
SteGONZALEZ's picture
integration Mkdocs au lieu de pydocs
89ecf2e
Raw
History Blame Contribute Delete
3.6 kB
"""
Gestion de la connexion à la base de données pour l’API TechNova Partners.
Ce module centralise :
- le chargement de la configuration de connexion à la base (DATABASE_URL),
- la création de l’engine SQLAlchemy,
- la configuration des sessions,
- la dépendance FastAPI permettant d’injecter une session DB dans les endpoints.
Objectif
---------------------------------------
Séparer clairement la logique "base de données" du reste de l’application permet :
- d’éviter les duplications de code,
- de faciliter les tests (SQLite en mémoire),
- de rendre le projet plus lisible et plus professionnel.
Comportement selon l’environnement
----------------------------------
- En développement / production :
- les variables sont chargées depuis un fichier `.env`
- DATABASE_URL pointe généralement vers PostgreSQL
- En tests (pytest) :
- pytest définit automatiquement `PYTEST_CURRENT_TEST`
- le chargement du `.env` est désactivé
- les tests peuvent fournir leur propre DATABASE_URL (ex: SQLite en mémoire)
Base supportée
--------------
- PostgreSQL (recommandé en production)
- SQLite (utilisé pour les tests et le développement rapide)
Le code est compatible SQLAlchemy 2.x.
"""
from __future__ import annotations
import os
from typing import Generator
from dotenv import load_dotenv, find_dotenv
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
# Charger les variables d'environnement depuis .env, sauf si on est dans un contexte de test
# (pytest définit la variable d'environnement PYTEST_CURRENT_TEST)
if "PYTEST_CURRENT_TEST" not in os.environ:
load_dotenv(find_dotenv())
# Si PYTEST_CURRENT_TEST est défini, on suppose que les tests gèrent eux-mêmes les variables
# d'environnement nécessaires (par exemple via des fixtures pytest)
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite+pysqlite:///:memory:")
# SQLAlchemy 2.0 recommande d'utiliser future=True pour préparer la transition vers la nouvelle API,
# et pool_pre_ping=True pour éviter les erreurs de connexion "MySQL server has gone away"
engine = create_engine(
DATABASE_URL,
pool_pre_ping=True,
future=True,
connect_args={"check_same_thread": False}
if DATABASE_URL.startswith("sqlite")
else {},
)
# sessionmaker est configuré pour ne pas faire de commit automatique,
# ne pas faire de flush automatique, et ne pas expirer les objets après commit (expire_on_commit=False)
# pour éviter les problèmes d'accès aux données après le commit
SessionLocal = sessionmaker(
bind=engine,
autocommit=False,
autoflush=False,
expire_on_commit=False,
)
# Dependency pour obtenir une session de base de données dans les endpoints FastAPI,
# avec gestion automatique de la fermeture de la session après usage
def get_db() -> Generator[Session, None, None]:
"""
Fournit une session de base de données à un endpoint FastAPI.
Cette fonction est utilisée comme dépendance (`Depends(get_db)`).
Fonctionnement :
- ouvre une session SQLAlchemy,
- la met à disposition de l’endpoint,
- garantit sa fermeture après la requête (même en cas d’erreur).
Pourquoi ?
---------------------------
- évite les fuites de connexions,
- garantit une gestion propre du cycle de vie des sessions,
- respecte les bonnes pratiques FastAPI + SQLAlchemy.
Yields
------
sqlalchemy.orm.Session
Session active connectée à la base de données.
"""
db = SessionLocal()
try:
yield db
finally:
db.close()