Top 10 des erreurs commises par les développeurs de Django
Publié: 2022-03-11Dans ce didacticiel, nous examinerons certaines erreurs courantes souvent commises par les développeurs de Django et les moyens de les éviter. Ce didacticiel est utile même si vous êtes un développeur Django expérimenté, car les erreurs, telles que la gestion de paramètres volumineux ou les conflits de nommage dans les ressources statiques, ne se limitent pas aux nouveaux développeurs qui tentent leur premier coup avec Django.
Django est un framework Web Python gratuit et open source qui résout utilement les défis de développement courants et vous permet de créer des applications flexibles et bien structurées. Django a beaucoup de fonctionnalités modernes prêtes à l'emploi. Pour moi personnellement, les fonctionnalités d'administration, de mappage objet-relationnel (ORM), de routage et de création de modèles ont fait de Django mon premier choix car les applications nécessitent beaucoup de travail et, bien que j'apprécie mon travail autant que n'importe quel développeur, je veux passer le moins de temps possible sur ces tâches répétitives de base. Django vous permet de faire tout cela sans compromettre la flexibilité.
La fonctionnalité killer de Django est une puissante interface d'administration configurable qui se construit automatiquement (automagiquement ?) à partir des modèles de schéma et de panneau d'administration de vos modèles, vous donnant l'impression d'être un assistant. Grâce à l'interface d'administration, un utilisateur peut configurer de nombreuses choses, notamment la liste de contrôle d'accès (ACL), les autorisations et les actions au niveau des lignes, les filtres, les commandes, les widgets, les formulaires, les assistants d'URL supplémentaires et tout ce que vous pouvez imaginer. Je pense que chaque application nécessite un panneau d'administration. Si ce n'est pas encore le cas, ce n'est qu'une question de temps avant que votre application de base en ait besoin. Avec Django admin, vous pouvez en créer un rapidement et de manière flexible.
Django dispose d'un ORM puissant qui fonctionne avec toutes les principales bases de données prêtes à l'emploi. Comme il est paresseux, il n'accède à votre base de données que lorsque vous en avez besoin, contrairement aux autres ORM. Il prend en charge toutes les principales instructions (et fonctions) SQL que vous pouvez utiliser à partir de votre code source Python et se sent très à l'aise grâce aux fonctionnalités de Python.
Le moteur de template de Django est à la fois très flexible et puissant. Vous pouvez utiliser de nombreux filtres et balises standard ainsi que créer vos nouveaux filtres et balises personnalisés pour votre projet. Django prend en charge d'autres moteurs de modèles ainsi que les modèles Django, et il fournit une API pour une intégration facile d'autres moteurs de modèles via des fonctions de raccourci standard pour le traitement des modèles.
Django a beaucoup d'autres grandes fonctionnalités comme un routeur d'URL qui peut analyser les requêtes entrantes et créer de nouvelles URL à partir d'un schéma de routeur. Dans l'ensemble, le framework Django est une expérience agréable et chaque fois que vous avez besoin d'aide, lisez simplement la documentation.
Erreur n° 1 : utiliser l'environnement Python du système global pour les dépendances de projet
N'utilisez pas l'environnement global de Python pour les dépendances de projet, car il peut produire des conflits de dépendance. Python ne peut pas utiliser plusieurs versions de package en même temps. Cela peut être un problème si différents projets nécessitent différentes versions incompatibles du même package.
Cette erreur est généralement commise par les nouveaux développeurs Python et Django qui ne connaissent pas les fonctionnalités d'isolation de l'environnement de Python.
Il existe de nombreuses façons d'isoler votre environnement, mais les plus courantes sont les suivantes :
- virtualenv : un package Python qui génère un dossier d'environnement Python et contient des scripts pour [dés]activer l'environnement et gérer les packages Python installés dans l'environnement. C'est ma méthode préférée car c'est la façon la plus simple de faire le travail. Habituellement, je crée l'environnement à proximité du dossier du projet.
- virtualenvwrapper : un package Python qui s'installe globalement et fournit un ensemble d'outils pour créer/supprimer/activer/etc. environnements virtuels. Tous les environnements virtuels sont stockés dans un dossier (qui peut être remplacé par la variable d'environnement WORKON_HOME). Je ne vois aucun avantage à utiliser
virtualenvwrapperau lieu devirtualenv. - Machines virtuelles (VM) : Il n'y a pas de meilleur isolement qu'une machine virtuelle entière dédiée à votre application. Il existe de nombreux outils parmi lesquels choisir, notamment VirtualBox (gratuit), VMware, Parallels et Proxmox (mon préféré, et il a une version gratuite). Combiné avec un outil d'automatisation de VM comme Vagrant, cela peut être une solution extrêmement puissante.
- Conteneurs : Au cours des dernières années, j'ai utilisé Docker dans presque tous les projets, en particulier dans chaque nouveau projet que je démarre à partir de zéro. Docker est un outil incroyable qui fournit de nombreuses fonctionnalités et dispose de nombreux outils tiers pour l'automatisation des conteneurs. Il dispose d'une fonction de mise en cache des couches qui rend la reconstruction de vos conteneurs extrêmement rapide. Dans les conteneurs, j'utilise l'environnement Python du système global, car chaque conteneur a son propre système de fichiers et les projets sont isolés au niveau supérieur. Docker permet aux nouveaux membres de l'équipe de commencer à travailler sur le projet plus rapidement, surtout s'ils ont une expérience Docker.
Si vous me demandez, je préfère le package virtualenv Python et les conteneurs Docker pour l'isolation et la gestion des dépendances du projet.
Erreur n° 2 : ne pas épingler les dépendances du projet dans un fichier requirements.txt
Chaque nouveau projet Python doit commencer par un fichier requirements.txt et un nouvel environnement isolé. Normalement, vous installez tous les packages via pip/easy_install mais n'oubliez jamais de les ajouter également à votre fichier requirements.txt . Cela facilite ( peut -être mieux) le déploiement de votre projet sur des serveurs, ou permet à un membre de l'équipe de démarrer le projet sur sa propre machine.
De plus, il est tout aussi important d' épingler la version spécifique de vos dépendances dans votre fichier requirements.txt . Généralement, différentes versions d'un package fournissent différents modules, fonctions et paramètres de fonction ; même un changement de version mineur dans une dépendance peut casser votre paquet. Il s'agit d'un problème très sérieux si votre projet est en ligne et que vous avez régulièrement planifié des déploiements car, sans versioning, votre système de construction installera toujours la dernière version disponible du package.
Épinglez toujours vos colis pour la production ! Personnellement, j'utilise un très bel outil appelé pip-tools qui m'aide à le faire. Il fournit un ensemble d'outils de ligne de commande qui vous aident à gérer vos dépendances. Il génère automatiquement un requirements.txt qui épingle non seulement vos dépendances, mais l'intégralité de votre arborescence de dépendances, qui inclut les dépendances de vos dépendances.
Parfois, vous souhaitez mettre à jour uniquement certains packages de votre liste de dépendances (par exemple, uniquement Django/Flask/un framework ou un utilitaire), si vous avez utilisé "pip freeze", vous ne savez pas quelles dépendances sont pour quels packages, et donc vous ne peut pas mettre à niveau une dépendance. Avec pip-tools, cependant, il épingle automatiquement les packages en fonction de la dépendance que vous avez épinglée, de sorte qu'il résout automatiquement les packages qui doivent être mis à jour. En prime, vous savez également exactement quel paquet provient de quelle dépendance en raison de la façon dont il les marque avec des commentaires dans le fichier requirements.txt .
Pour être encore plus prudent, c'est une bonne idée de sauvegarder également vos fichiers sources de dépendances ! Conservez une copie dans votre système de fichiers, un dossier géré par Git, un dossier S3, FTP, SFTP, où que vous soyez, mais ayez-le à portée de main. Il y a eu des cas où un paquet relativement mineur non répertorié a cassé un grand nombre de paquets sur npm. Pip fournit utilement l'outil pour télécharger toutes les dépendances requises en tant que fichiers source, lisez plus en exécutant pip help download .
Erreur n° 3 : utiliser des fonctions Python à l'ancienne au lieu de vues basées sur des classes
Parfois, c'est une bonne idée d'utiliser une petite fonction Python dans le fichier views.py d'une application, en particulier pour les tests ou les vues utilitaires, mais en général, vous devez utiliser des vues basées sur les classes (CBV) dans vos applications.
Les CBV sont des vues génériques qui fournissent des classes abstraites implémentant des tâches de développement Web courantes construites par des professionnels et couvrant tous les comportements courants. Ils ont une API structurée étonnante et vous pouvez utiliser tous les avantages de la programmation orientée objet lorsque vous utilisez des CBV. Cela rend votre code source plus clair et lisible. Oubliez la douleur d'utiliser les fonctions d'affichage standard de Django pour les listes, les opérations CRUD, le traitement des formulaires, etc. crée des spaghettis à partir de votre code source en cas d'utilisation de fonctions d'affichage au lieu de CBV) qui configurent le comportement de l'affichage.
Par exemple, vous pouvez avoir différents mix-ins dans votre projet qui remplacent les comportements CBV de base pour la création de contextes de vue, la vérification de l'autorisation au niveau de la ligne, la création automatique de chemins de modèles à partir de la structure de votre application, l'intégration de la mise en cache intelligente, etc.
J'ai construit le package nommé Django Template Names, qui normalise les noms de modèles pour vos vues en fonction d'un nom d'application et d'un nom de classe de vue. Je l'utilise tous les jours et cela me fait gagner beaucoup de temps pour inventer des noms. Mettez simplement le mixin dans votre CBV — class Detail(TemplateNames, DetailView): — et il commencera à fonctionner ! Bien sûr, vous pouvez remplacer mes fonctions et ajouter des modèles réactifs mobiles, différents modèles pour les agents utilisateurs ou tout ce que vous voulez.
Erreur n° 4 : Écrire des vues grasses et des modèles maigres
Écrire votre logique d'application dans des vues au lieu de modèles signifie que vous avez écrit du code qui appartient à votre modèle dans la vue, ce qui le rend « gros » et votre modèle « maigre ».
Vous devriez écrire des modèles gras, des vues maigres.
Décomposez la logique en petites méthodes sur vos modèles. Cela vous permet de l'utiliser plusieurs fois à partir de plusieurs sources (interface utilisateur de l'interface d'administration, interface utilisateur frontale, points de terminaison API, vues multiples) en quelques lignes de code au lieu de copier-coller des tonnes de code. Ainsi, la prochaine fois que vous enverrez un e-mail à un utilisateur, étendez le modèle avec une fonction d'e-mail au lieu d'écrire cette logique dans votre contrôleur.
Cela facilite également le test unitaire de votre code, car vous pouvez tester la logique de messagerie à un seul endroit, plutôt que de manière répétée dans chaque contrôleur où cela se produit.
Vous pouvez en savoir plus sur le problème dans le projet Django Best Practices. La solution est simple : écrivez des modèles épais et des vues étroites, alors faisons-le dans votre prochain projet (ou refactorisez votre projet actuel).
Erreur n° 5 : un fichier de paramètres énorme et ingérable
Même le nouveau fichier de paramètres du projet Django a beaucoup de paramètres. Dans un projet réel, un fichier de paramètres atteint plus de 700 lignes de configuration et va devenir difficile à maintenir, en particulier lorsque vos environnements de développement, de production et de mise en scène ont tous besoin de configurations personnalisées.

Vous pouvez diviser le fichier de configuration manuellement et créer des chargeurs personnalisés, mais je souhaite vous présenter un package Python agréable et bien testé, Django Split Settings, que j'ai co-écrit.
Le package fournit deux fonctions, optional et incluses include qui prennent en charge les caractères génériques pour les chemins et importent vos fichiers de configuration dans le même contexte, ce qui simplifie la création de votre configuration à l'aide des entrées de configuration déclarées dans les fichiers précédemment chargés. Cela n'affecte pas les performances de Django et vous pouvez l'utiliser dans n'importe quel projet.
Découvrez l'exemple de configuration minimale :
from split_settings.tools import optional, include include( 'components/base.py', 'components/database.py', 'components/*.py', # the project different envs settings optional('envs/devel/*.py'), optional('envs/production/*.py'), optional('envs/staging/*.py'), # for any local settings optional('local_settings.py'), )Erreur n° 6 : Application tout-en-un, mauvaise structure d'application et mauvais placement des ressources
Tout projet Django se compose de plusieurs applications. En notation Django, une application est un package Python qui contient au moins les fichiers __init__.py et models.py ; dans les dernières versions de Django, models.py n'est plus nécessaire. __init__.py suffit.
Les applications Django peuvent contenir des modules Python, des modules spécifiques à Django (vues, URL, modèles, admin, formulaires, balises de modèle, etc.), des fichiers statiques, des modèles, des migrations de bases de données, des commandes de gestion, des tests unitaires, etc. Vous devez diviser vos applications monolithiques en petites applications réutilisables en utilisant une logique simple. Vous devriez être en mesure de décrire l'intégralité de l'objectif de l'application en une ou deux phrases courtes. Par exemple : "Permet aux utilisateurs de s'inscrire et d'activer leur compte par e-mail."
C'est une bonne idée d'appeler le dossier du projet project et de placer les applications dans project/apps/ . Ensuite, placez toutes les dépendances d'application dans leurs propres sous-dossiers.
Exemples:
- Fichiers statiques :
project/apps/appname/static/appname/ - Balises de modèle :
project/apps/appname/templatetags/appname.py - Fichiers de modèle :
project/apps/appname/templates/appname/
Préfixez toujours le nom de l'application dans les sous-dossiers car tous les dossiers statiques sont fusionnés dans un dossier et, si deux applications ou plus avaient un fichier js/core.js , la dernière application dans settings.INSTALLED_APPLICATIONS remplacera les précédentes. Une fois, j'ai eu ce bogue dans mon projet actuel et j'ai perdu environ six heures de débogage jusqu'à ce que je réalise qu'un autre développeur avait remplacé static/admin/js/core.js parce que l'équipe implémentait un panneau d'administration SPA personnalisé et nommait ses fichiers de la même manière.
Voici un exemple de structure pour une application de portail qui a beaucoup de ressources et de modules Python.
root@c5b96c395cfb:/test# tree project/apps/portal/ project/apps/portal/ ├── __init__.py ├── admin.py ├── apps.py ├── management │ ├── __init__.py │ └── commands │ ├── __init__.py │ └── update_portal_feeds.py ├── migrations │ └── __init__.py ├── models.py ├── static │ └── portal │ ├── css │ ├── img │ └── js ├── templates │ └── portal │ └── index.html ├── templatetags │ ├── __init__.py │ └── portal.py ├── tests.py ├── urls.py └── views.py 11 directories, 14 filesEn utilisant une telle structure, vous pouvez à tout moment exporter l'application dans un autre package Python et l'utiliser à nouveau. Vous pouvez même le publier dans PyPi en tant que package open source ou le déplacer vers un autre dossier.
Vous vous retrouverez avec une structure de projet comme celle-ci :
root@c5b96c395cfb:/test# tree -L 3 . ├── deploy │ ├── chef │ └── docker │ ├── devel │ └── production ├── docs ├── logs ├── manage.py ├── media ├── project │ ├── __init__.py │ ├── apps │ │ ├── auth │ │ ├── blog │ │ ├── faq │ │ ├── pages │ │ ├── portal │ │ └── users │ ├── conf │ ├── settings.py │ ├── static │ ├── templates │ ├── urls.py │ └── wsgi.py └── static └── admin ├── css ├── fonts ├── img └── js 25 directories, 5 filesDans un projet réel, bien sûr, ce sera plus complexe, mais cette structure rend les choses plus simples et plus propres.
Erreur n° 7 : STATICFILES_DIRS et STATIC_ROOT confondent les développeurs Django débutants
Les fichiers statiques sont des actifs qui ne changent pas lors de l'utilisation de l'application, par exemple, JavaScript, CSS, images, polices, etc. Dans Django, ils sont uniquement « collectés » dans un répertoire public pendant le processus de déploiement.
En mode développement python manage.py runserver Django recherche les fichiers statiques à l'aide du paramètre STATICFILES_FINDERS . Par défaut, il essaie de trouver le fichier statique demandé dans les dossiers répertoriés dans le paramètre STATICFILES_DIRS . En cas d'échec, Django essaie de trouver le fichier en utilisant django.contrib.staticfiles.finders.AppDirectoriesFinder , qui regarde dans le dossier static de chaque application installée dans le projet. Cela vous permet d'écrire des applications réutilisables qui sont livrées avec leurs propres fichiers statiques.
En production, vous servez votre statique à l'aide d'un serveur Web autonome comme Nginx. Le serveur Web ne sait rien de la structure des applications du projet Django ni des dossiers dans lesquels vos fichiers statiques sont distribués. Heureusement, Django vous fournit la commande de gestion collect static python manage.py collectstatic , qui parcourt STATICFILES_FINDERS et copie tous les fichiers statiques des applications static dossiers et dossiers répertoriés dans STATICFILES_DIRS dans le répertoire que vous spécifiez dans le paramètre STATIC_ROOT . Cela permet la résolution des ressources de fichiers statiques en utilisant la même logique que le serveur en mode développement Django et a tous les fichiers statiques en un seul endroit pour votre serveur Web.
N'oubliez pas d'exécuter collectstatic dans votre environnement de production !
Erreur n ° 8 : STATICFILES_STORAGE par défaut, chargeurs de modèles Django en production
STATICFILES_STORAGE
Parlons de la gestion des actifs de l'environnement de production. Nous pouvons offrir la meilleure expérience utilisateur si nous appliquons une politique « les actifs n'expirent jamais » (sur laquelle vous pouvez en savoir plus ici). Cela signifie que tous nos fichiers statiques doivent être mis en cache par les navigateurs Web pendant des semaines, des mois, voire des années. En d'autres termes, vos utilisateurs ne doivent télécharger vos ressources qu'une seule fois !
C'est cool, et nous pouvons le faire avec quelques lignes dans la configuration Nginx pour notre dossier de fichiers statiques, mais qu'en est-il de l'invalidation du cache ? Si l'utilisateur ne télécharge nos ressources qu'une seule fois, que se passe-t-il si vous mettez à jour votre logo, vos polices, JavaScript ou la couleur du texte d'un élément d'un menu ? Pour contourner cela, vous devez générer des URL et des noms de fichiers uniques pour nos fichiers statiques à chaque déploiement !
Nous pouvons le faire simplement en utilisant ManifestStaticFilesStorage comme STATICFILES_STORAGE (attention, le hachage n'est activé qu'en mode DEBUG=false ) et en exécutant la commande de gestion collectstatic décrite ci-dessus. Cela réduira le nombre de demandes d'actifs sur votre site Web de production et rendra votre site Web beaucoup plus rapide.
Chargeur de modèles Django en cache
Une autre fonctionnalité intéressante de Django est le chargeur de modèles mis en cache, qui ne recharge pas et n'analyse pas les fichiers de modèles à chaque rendu de modèle. L'analyse de modèles est une opération très coûteuse et utilise beaucoup de ressources. Par défaut, les modèles Django sont analysés à chaque requête, mais c'est mauvais, surtout pendant la production, où vous pouvez traiter des milliers de requêtes en peu de temps.
Consultez la section de configuration cached.Loader pour un bon exemple et des détails sur la façon de procéder. N'utilisez pas le chargeur en mode développement car il ne recharge pas les modèles analysés à partir du système de fichiers ; vous devrez redémarrer votre projet en utilisant python manage.py startapp à chaque changement de modèle. Cela peut être gênant pendant le développement, mais c'est parfait pour l'environnement de production.
Erreur n° 9 : Scripts Python purs pour les utilitaires ou les scripts
Django fournit une fonctionnalité très intéressante appelée Commandes de gestion. Utilisez-le simplement au lieu de réinventer les roues et d'écrire des scripts Python bruts pour les utilitaires de votre projet.
Consultez également le package Django Extensions, qui est une collection d'extensions personnalisées pour Django. Peut-être que quelqu'un a déjà implémenté vos commandes ! Il existe déjà un grand nombre de commandes de tâches courantes.
Erreur n°10 : réinventer la roue
Django et Python ont des milliers de solutions prêtes à l'emploi. Essayez de googler avant d'écrire quelque chose qui n'est pas unique ; il existe probablement une solution riche en fonctionnalités qui existe déjà.
Essayez simplement de simplifier les choses. Google d'abord ! Installez, configurez, étendez et intégrez dans votre projet si vous trouvez un package de bonne qualité et, bien sûr, contribuez à l'open source lorsque vous en avez l'occasion.
Pour commencer, voici une liste de mes propres packages publics pour Django :
- Django Macros URL facilite l'écriture (et la lecture) de modèles d'URL dans vos applications Django à l'aide de macros.
- Django Templates Names est un petit mix-in qui vous permet de standardiser facilement les noms de vos modèles CBV.
- django-split-settings vous permet d'organiser les paramètres Django en plusieurs fichiers et répertoires. Remplacez et modifiez facilement les paramètres. Utilisez des caractères génériques dans les chemins d'accès aux fichiers de paramètres et marquez les fichiers de paramètres comme facultatifs.
Ne vous répétez pas (DRY) !
J'aime beaucoup la méthodologie DRY ; c'est pourquoi j'ai créé Django squelette comme un outil pratique qui a des fonctionnalités vraiment intéressantes prêtes à l'emploi :
- Des images Docker pour le développement/production, gérées par docker-compose, qui permettent d'orchestrer facilement une liste de conteneurs.
- Script Fabric simple pour le déploiement en production.
- Configuration pour le package Django Split Settings avec les paramètres pour les sources de base et locales.
- Webpack intégré au projet - Seul le dossier
distsera collecté par Django sur la commandecollectstatic. - Configuration de tous les paramètres et fonctionnalités de base de Django, tels que les modèles Django pouvant être mis en cache en production, les fichiers statiques hachés, la barre d'outils de débogage intégrée, la journalisation, etc.
C'est un Django Skeleton prêt à l'emploi pour votre prochain projet à partir de zéro et, espérons-le, vous fera gagner beaucoup de temps en amorçant votre projet. Webpack a une configuration de base minimale, mais il a également installé SASS préconfiguré pour gérer les fichiers .scss .
