Bien démarrer un projet Django
S’il y a bien une première question existentielle avec Django, c’est de savoir comment structurer son projet.
Quand on vient, comme moi, de frameworks PHP à l’architecture de fichiers beaucoup plus strict, la liberté d’action inhérente au Python peut dérouter plus d’un développeur.
Dans ce post je vais vous présenter ma façon de structurer mes projets Django. Celle-ci se base sur plusieurs bonnes pratiques, mais n’est bien sûr pas la seule solution possible.
Nous allons partir “from scratch”, et à la fin du post vous aurez une installation de la dernière version de Django (1.8.3 à l'heure où j'écris ces lignes) tournant sous python3.4, avec une architecture de dossier qui a fait ses preuves. Je suis sous OSX donc ceux sur Linux ne devraient pas avoir trop de problèmes à suivre. Pour les windowsiens il faudra peut-être faire quelques petites recherches Google en plus de temps en temps ;) .
Expand
Création de l'environnement virtuel
Pour ce post, je pars du principe que python 3 est déjà installé sur votre machine.
Lorsque l'on développe un projet, celui-ci a des dépendances, doit tourner sur une version précise de python, etc. Lorsque plusieurs projets python cohabitent sur la même machine, toutes les dépendances sont installées au même endroit. Pas de problème vous dites ? Imaginez que deux projets aient la même dépendances, mais pas pour la même version du paquet, ça devient un vrai casse tête !
Que diriez vous de pouvoir plutôt gérer les dépendances de chaque projet indépendament des autres ? Avoir un projet A sur python2.7 avec ses propres dépendances, cohabiter avec un projet B sur python3.4 avec lui aussi ses propres dépendances ? C'est ce que permet de faire un environnement virtuel :).
Installer virtualenv et virtualenwrapper
Tout d'abord, virtualenv est l'outil qui va nous servir à créer des environnements python isolés.
S'il peut se suffire à lui même, il est très fréquent d'utiliser la suite d'extensions virtualenvwrapper pour faciliter notre manipulation des virtualenv.
Installons donc tout ça grâce aux commandes suivantes :
https://gist.github.com/b333aa215053e74d6194
Créer un virtualenv sous python3
J'ai pour habitude de donner le même nom que le projet qu'ils contiennent à mes virtualenv. Créons donc ici un nouveau virtualenv "my_new_project" :
https://gist.github.com/28b4af37b3ecc00fb630
La commande which vous permet de trouver l'emplacement de python3 sur votre machine. Emplacement qu'il suffit de passer Ă la commande mkvirtualenv via l'argument --python.
Si tout se déroule correctement, vous devriez voir apparaître ce genre de message :
https://gist.github.com/3fffa722be285c819bc7
Les parenthèse contenant le nom de notre virtualenv indiquent que nous sommes bien dans notre nouvel environnement virtuel :) .
La première fois que l'on utilise un virtualenv on peut légitimement se demander si la commande mkvirtualenv doit s'effectuer depuis le futur emplacement du code source de notre projet.
La réponse est : peu importe !
En fait ce qu'il faut bien comprendre avec les environnement virtuels c'est que l'emplacement de votre code source lui importe peu. Votre code source lui par contre ne s'en fiche pas !
En gros sans environnement virtuel vos packages installés le sont dans l'installation globale de votre machine. En utilisant un virtualenv, les packages installés le seront à l'emplacement du virtualenv, ne polluant ainsi pas l'espace global ! C'est tout là l'intérêt ;) .
Désactiver et activer un virtualenv grâce à virtualenvwrapper
Si vous avez bien suivi jusque ici, votre virtualenv doit être activé. Vous pouvez le désactiver tout simplement grâce à la commande deactivate. Les parenthèses disparaissent, votre virtualenv est correctement désactivé.
Lorsque vous souhaitez travailler sur un projet et que vous souhaitez donc activer le virtualenv correspondant, c'est un jeu d'enfant, dans notre cas il suffirait simplement d'écrire : workon my_new_projet.
Installation et architecture du projet
Nous rentrons maintenant dans le vif du sujet. Installons la dernière version de Django grâce à la commande : pip install django.
Pour informations je suis en train de développer un projet perso nommé trackr donc quand vous verrez ce nom, remplacez le dans votre tête par le nom de votre projet ;)
Maintenant que Django est bien téléchargé, mettez vous dans le dossier où vous voulez créer votre projet et créez-y un nouveau dossier, pour moi ce sera donc :
https://gist.github.com/f5421fa4d8b3ef7f4b81
Dans ce post, je présume que vous savez déjà utiliser git. Initialisons donc un nouveau repo git grâce à la commande git init. Nous pouvons maintenant générer notre nouveau projet à proprement parler : django-admin startproject nom_de_votre_projet.
Nous nous retrouvons avec l'architecture suivante :
https://gist.github.com/8e16ca0a02abbb469900
J'ai tout de suite tendance à créer quelques fichiers/dossiers supplémentaires :
https://gist.github.com/7c1da4330d39f5928219
README.rst : bon pour celui-là pas vraiment besoin de détails, c'est un classique !
docs/ : ce dossier est utile si vous avez besoin de créer une documentation pour votre projet. C'est un bon endroit pour la placer.
requirements/ : c'est le dossier qui contiendra les différents fichier requirements-.txt. On détaillera ça un peu plus tard.
Il reste maintenant à créer le dossier qui accueillera les fichiers statiques principaux, celui qui accueillera les templates généraux, et créer les différents fichiers en fonctions de vos environnements de travail :
https://gist.github.com/324d65305bfda294d251
Vous remarquerez que le fichier settings.py de base a laissé sa place à un dossier settings contenant un fichier base.pyqui est en faite une copie du fichier settings.py généré par Django. On a souvent tendance à oublier qu'un fichier settingsn'est rien d'autre qu'un module python, on peut donc très facilement modifier uniquement les settings qui nous interressent en important les settings de base grâce à la commande from .base import *. Ouvrez donc tous les fichiers settings autre que base.py et ajoutez-y cet import en haut du fichier.
Il est généralement déconseillé d'utiliser import *, mais concernant les settings, ça ne posera pas de problème.
Les plus attentifs auront remarqué que nous n'avons pas de fichier settings staging.py mais juste un fichier settings production.py, alors même que l'on fait pourtant la distinction dans le dossier requirements/ ! Sans rentrer trop dans les détails, sachez juste que comme l'environnement de staging doit être le plus similaire possible à l'environnement de production, il n'a pas de raison d'avoir des settings différentes. Par contre il se peut (notamment pour certains tests fonctionnels, mais ce n'est pas le sujet ici) que vous ayez besoin de paquets particulier sur staging dont vous n'aurez pas besoin en production.
VoilĂ une bonne chose de faite. Nous avons maintenant besoin d'indiquer Ă Django quel fichier de settings il doit utiliser. En l'occurrence, nous avons besoin d'utiliser en local le fichier local.py.
Il est possible de spécifier à Django le fichier de settings à utiliser grâce à la variable d'environnement DJANGO_SETTINGS_MODULE. Vous voyez ici tout l'intérêt d'un environnement virtuel ? Si nous avions plusieurs projets dans l'environnement global de notre machine, cette variable aurait été commune à tous les projets. Un petit peu embêtant quand même...
Normalement votre virtualenv devrait être toujours actif à ce stade, si vous tapez simplement la commande export DJANGO_SETTINGS_MODULE='trackr.settings.local ("trackr" est bien sûr à remplacer par le nom de votre propre projet, nous faisons ici référence au fichier trackr/trackr/settings/local.py), et que vous tapez echo $DJANGO_SETTINGS_MODULE vous devriez voir apparaître sans grande surprise trackr.settings.local'. C'est bien beau tout ça mais si vous faites undeactivatesuivi d'unworkon trackrvous observerez la commandeecho` précédente n'affichera plus rien !
Pour faire en sorte que la variable soit définie à chaque fois que nous démarrons le virtualenv, il faut la définir dans le fichier activate présent dans le dossier bin de votre virtualenv. Ouvrez ce fichier et mettez-y à la fin export DJANGO_SETTINGS_MODULE='trackr.settings.local'. Si vous désactivez votre virtualenv et que vous le réactivez, la variable sera accessible avec la bonne valeur :) .
Configuration des settings de base
La prochaine étape est de modifier quelque peu notre fichier settings/base.py automatiquement généré par Django.
Premier réflexe, les données sensibles comme la SECRET_KEY ne doivent pas être versionnées. Nous allons donc récupérer cette valeur grâce à une variable d'environnement.
Ajoutez dans une variable DJANGO_SECRET_KEY (le nom importe peu) dans le fichier bin/activate de votre virtualenv : export DJANGO_SECRET_KEY='abcdeghijklmnopqrstuvwxyz0123456789'
Désactivez votre virtualenv et réactivez-le pour que la variable soit correctement exportée.
Modifiez maintenant le fichier settings/base.py pour récupérer la SECRET_KEY depuis la variable d'environnement :
https://gist.github.com/d933e7b0ebfa32dcd8e5
Il ne faut donc pas oublier de déclarer cette variable d'environnement ! Pour pallier ce petit désagrément, pourquoi ne pas lancer une exception ImproperlyConfigured si jamais la variable d'environnement n'existe pas ? C'est très simple, je vous propose ce petit snippet :
https://gist.github.com/e724c0f2caa90f3f1650
Généralement, le dossier trackr/track/ est le dossier racine de votre projet, et le dossier trackr/trackr/trackr/ est le dossier de configuration de votre projet. Nous allons avoir besoin de ces informations, ajoutons-les dans le fichier settings/base.py :
https://gist.github.com/4c9db666187fc9a46c05
N'oubliez pas de mettre la variable DEBUG à False dans le fichier settings/base.py, et du coup de surcharger ça dans votre fichier settings/local.py:
https://gist.github.com/891920ed39c3c38538d4
Fichiers statiques et médias
Sujet sensible en vu ! Les premiers problèmes que l'on rencontre souvent avec Django sont liés à une mauvaise configuration des settings liées aux fichiers statiques, aux médias, et aux templates. Pour rester simple, nous n'allons pas aborder dans ce post la gestion des fichiers statiques sur un serveur distant en production. Nous restons en local pour le moment.
Tout d'abord, nous devons spécifier les settings STATIC_URL, MEDIA_URL et MEDIA_ROOT :
https://gist.github.com/a06aa13da285adc1c572
Nous n'avions pas encore parlé du dossier trackr/trackr/trackr/media. C'est l'emplacement où se trouveront les fichiers uploadés à travers notre site. Mais attention ce dossier est exclusivement réservé à un usage local, en production ce sera géré différemment.
Nous devons maitenant indiquer à Django qu'il doit récupérer nos fichiers statiques en cherchant dans les dossiers static de nos applications, en commençant à traverser notre arborescence par le dossier static situé à la raçine de notre projet, grâce aux settings STATICFILES_FINDERS et STATICFILES_DIRS:
https://gist.github.com/4f624b170c7469fbe146
A noter que si vous souhaitez gérer en local les fichiers médias, vous devrez ajouter une url dans le fichier urls.py de base de votre projet :
https://gist.github.com/01781e16f9409cddeeb6
Il vous faudra donc ajouter dans votre fichier settings/base.py : SERVE_LOCAL_MEDIA = False pour, par défaut, ne pas servir les médias en local, mais du coup ajouter dans votre fichier settings/local.py : SERVE_LOCAL_MEDIA = True.
Petit point de détails, mais je trouve personnellement plus propre de séparer les applications tierces, des application django, de nos propres applications metiers. J'ai pour habitude d'écrire dans mon fichier settings/base.py:
https://gist.github.com/60b0b9f0880e4ee3c2c9
De la sorte, si nous avons besoin d'un module tiers spécifique uniquement pour notre environnement de test par exemple, il suffira d'écrire dans settings/test.py:
https://gist.github.com/9bc1c29cff9910e8f6a3
Vérification de la configuration
Il est temps de vérifier maintenant si ça fonctionne ! Tout d'abord je vous conseille de faire un petit chmod +x manage.py pour rendre votre fichier manage.py éxécutable, mine de rien ça évite d'avoir à écrire tout le temps python manage.py ... et écrire directement à la place ./manage.py ....
Il est temps de lancer la migration qui va finir "d'installer" Django. Il suffit simplement de lancer la commande : ./manage.py migrate. Si tout se passe bien vous devriez voir apparaître ce genre de messages :
https://gist.github.com/85a4ec03b9a3f7bf4248
Vous pouvez maintenant lancer le serveur en local pour tester tout ça : `./manage.py runserver``
En allant à l'adresse localhost:8000 vous devriez voir apparaître la page de démarrage de Django: Django first page
Vous avez maintenant une base solide pour développer votre projet Django sereinement. Du moins en local ! Car c'est une toute autre histoire dès qu'il s'agit de déployer l'application sur un serveur (ce qui est un peu le but quand même...).
Nous verrons donc dans un prochain post comment déployer son application sur Heroku et utiliser Amazon S3 pour gérer les fichiers statiques et médias. Tout un programme !
Si vous avez des questions ou que vous voyez des choses pas claires, n'hésitez pas à laisser un commentaire ;) .