Bonnes pratiques, tips et astuces autour de Python, Django, Django REST Framework, FastAPI et Flask. Approches TDD, SOLID et DDD pour des APIs backend solides.
Anthony.D
Développeur Python · Django · FastAPI · Flask · Freelance
Développeur Python · Django · FastAPI · Flask · Freelance
Bonnes pratiques, tips et astuces autour de Python, Django, Django REST Framework, FastAPI et Flask. Approches TDD, SOLID et DDD pour des APIs backend solides.

Par défaut, Django charge tous les champs d’un modèle à chaque requête. Sur une vue liste de 50 articles, cela signifie 50 fois le contenu complet, le résumé, les métadonnées, les champs de traduction, même si on n’affiche que le titre et la date. Quatre méthodes QuerySet Django permettent de contrôler précisément ce qui est chargé : defer(), only(), values_list() et Prefetch(). Résultat : 2 requêtes SQL au lieu de N+2, avec uniquement les colonnes nécessaires. ...

Après quelques mois de développement, il n’est pas rare d’accumuler 30, 50, voire 100 fichiers de migration sur une application Django. Chaque lancement de test qui repart d’une base vide les rejoue toutes. Chaque déploiement sur un nouvel environnement aussi. squashmigrations permet de fusionner plusieurs migrations en une seule, sans perdre la compatibilité avec les environnements déjà déployés. La commande et ce qu’elle génère La syntaxe prend une plage de migrations : ...

Deux requêtes simultanées lisent le stock d’un produit, constatent qu’il en reste un, et toutes les deux valident la commande. Le stock passe à -1. Ce type de condition de course est difficile à reproduire en développement et dévastateur en production. select_for_update() est la réponse de Django : poser un verrou SQL au moment de la lecture pour garantir qu’aucune autre transaction ne peut modifier la ligne avant la fin de l’opération. ...

Python crée par défaut un dictionnaire __dict__ pour chaque instance de classe. C’est flexible, pratique, mais coûteux en mémoire quand on instancie des milliers ou des millions d’objets. __slots__ est le mécanisme qui supprime ce dictionnaire et stocke les attributs dans une structure compacte. Gain typique : 40 à 60 % de mémoire en moins par instance. Ce que fait Python sans slots Sans rien déclarer, chaque instance porte son propre __dict__ : ...

Quand on expose des données depuis un modèle Django vers une API ou un serializer, les noms de champs du modèle ne correspondent pas toujours à ce qu’on veut retourner. Le réflexe habituel : récupérer les instances, puis renommer en Python. Il existe une meilleure option : laisser la base de données faire le travail via F() dans values(). Le problème : les noms de champs s’imposent class Task(models.Model): name = models.CharField(...) created_at = models.DateTimeField(...) Si on veut retourner nom_tache au lieu de name, on récupère les données puis on renomme en Python, soit via une compréhension de dict, soit dans le serializer. Dans les deux cas, la transformation se fait après coup, en mémoire. ...

On entend souvent “on a mis en place une API REST” dans les équipes. Mais quand on regarde les réponses JSON, il n’y a aucun lien. Juste des données brutes. Ce n’est pas du REST, c’est du CRUD exposé en HTTP. La différence tient à un principe que la plupart des développeurs ignorent : HATEOAS. Qu’est-ce que HATEOAS ? HATEOAS signifie Hypermedia As The Engine Of Application State. C’est l’une des contraintes fondamentales du REST, définie par Roy Fielding dans sa thèse de 2000 (la même qui a inventé le terme REST). ...

Avec Django ORM, il existe deux façons d’ajouter une valeur calculée sur un ensemble de lignes : annotate() avec une agrégation classique (Max, Count, Sum…) ou annotate() avec une Window function. En surface, elles se ressemblent. En pratique, elles ont un comportement fondamentalement différent, et choisir la mauvaise peut bloquer toute la chaîne de filtrage. GROUP BY avec annotate() : des lignes qui s’écrasent Quand on combine values() et annotate() avec une agrégation, Django génère un GROUP BY en SQL. Le résultat : les lignes se regroupent, et on obtient une ligne par groupe. ...

Quand on a une liste d’identifiants et qu’on veut récupérer les instances correspondantes, le réflexe habituel en Django c’est filter(pk__in=[...]). Ça marche, c’est une seule requête SQL. Mais in_bulk() est une optimisation ORM souvent ignorée : elle retourne un dictionnaire {id: instance} au lieu d’un QuerySet, ce qui change radicalement la façon d’accéder aux résultats. Là où filter() force un parcours O(n) pour retrouver un objet par son ID, in_bulk() donne un accès direct O(1). ...

On entend souvent la même promesse ces derniers temps : “Plus besoin de savoir coder, l’IA s’en charge.” Et franchement, c’est séduisant. On ouvre un agent, on décrit ce qu’on veut, et en quelques secondes, du code apparaît. Magique. Sauf que non. Pas vraiment. Le développement agentique, oui mais pour qui ? Le développement assisté par IA est une révolution réelle. Je ne vais pas prétendre le contraire. Pour un développeur senior ou intermédiaire, qui s’est déjà heurté à des problématiques complexes, débogué des algos tordus, et livré des systèmes en production, la productivité atteint des sommets inégalés. On délègue les tâches répétitives, on prototypé en heures ce qui prenait des jours, et on reste dans sa zone de haute valeur : l’architecture, les décisions critiques, la validation. ...

Ce blog, c’est avant tout un espace de partage : des découvertes, des réflexions, des choses qui m’ont été utiles et qui pourraient l’être pour d’autres. Python, Django, FastAPI et DRF : le cœur du blog Le cœur du blog, c’est le développement Python, et plus précisément les frameworks qui structurent mon quotidien : Django, FastAPI et Flask. Chacun a ses forces, ses cas d’usage, ses pièges. On rentrera dans le détail. ...