Pour ceux qui ont déjà fait du développement web avec Django le titre est évident, pour les autres, bienvenue sur mon introduction à Django !
Django est un excellent framework Python qui permet de développer rapidement des applications web, et qui est très complet. Il est plus long à prendre en main que Flask, un autre microframework Python que je vais utiliser comme exemple afin d'introduire quelques concepts de Django, et de montrer que ces idées bizarres ne sortent pas de nulle part.
Parés ? C'est parti !
# Prérequis
Ce tutoriel va référencer des tags du dépôt git [à cette adresse](https://git.hashtagueule.fr/motius/django-tutorial). Je vous conseille aussi [cet excellent tutoriel](https://tutorial.djangogirls.org/fr/) qui pourra compléter ce que j'écris ci-dessous. Enfin, la [documentation de Django](https://docs.djangoproject.com/) est complète et facile à utiliser.
Je vous conseille donc de cloner le dépôt ci-dessus :
Je préfixe les noms de tous les tags git de ce tutoriel par un `"_"`, afin que ceux-ci ne polluent pas le projet si vous en réutilisez le dépôt git par la suite (`git tag` admet l'option `-d` pour ceux qui veulent vraiment se débarasser de mes tags).
La quasi-totalité de ce tutoriel n'impose pas d'accès `root` sur le système de développement, je suppose tout de même que vous avez `python3` et `pip3` d'installés, un accès au réseau pour les packages Python supplémentaires, ainsi que le gestionnaire de versions de code`git`.
J'utilise une debian GNU/Linux 9.1 Stretch pour le développement, mais ce tutoriel doit facilement être adaptable à d'autres distributions.
Commençons en douceur avec Flask.
# Flask, en deux mots
Je vais me faire battre, je vais parler de Flask alors que je l'ai utilisé en tout et pour tout 7 minutes 24 secondes dans ma courte vie.
La partie intéressante que je voulais mettre en avant avec cet exemple concerne la structure du code Flask : j'ai divisé le source en trois parties, les imports, les routes Flask, et le code pour faire tourner l'application. La deuxième partie concernant les routes et le code métier est celle qui nous intéresse.
tandis que le code à exécuter dans le cas où l'utilisateur demande (`'GET'`) la page par défaut de l'application (`'/'`) se situe dans le code de la fonction Python `index`, qui dans notre cas retourne la chaîne de caractères `"Hello World!"` (tradition oblige) :
Ainsi, Flask pose les bases de la programmation avec [le motif MVC](https://fr.wikipedia.org/wiki/Mod%C3%A8le-vue-contr%C3%B4leur), que Django utilise : on décrit de manière séparée le code de routage des URL et le code permettant d'obtenir le résultat demandé.
Django utilisera des fichiers séparés pour le routage (Vues) et pour les fonctions Python du Contrôleur, mais le principe est le même.
Il va falloir un peu de travail pour arriver au même résultat avec Django, mais n'aillez pas peur, on y arrivera. L'essentiel est de garder les yeux sur l'objectif : avoir une séparation entre le code de routage et le code métier.
Django va un peu plus loin car il permet de s'interfacer très facilement avec une base de données et en propose une abstraction très propre, il possède un moteur de template pour prémâcher du HTML, permet d'installer des modules, mais tout ça viendra plus tard, je vous mets l'eau à la bouche...
La [page de téléchargement de Django](https://www.djangoproject.com/download/) indique, à l'heure actuelle, qu'il suffit de taper la commande suivante pour installer la dernière version de Django :
Si vous utilisez Django de manière professionnelle ou amateure, il faut consulter la page de téléchargement pour mettre à jour la version de Django utilisée.
Vous pouvez aussi installer la version de votre distribution, par exemple à l'aide de
Python est un langage de programmation modulaire dont le cœur des fonctionnalités est assez réduit, mais qui reste très puissant grâce au grand écosystème disponible de bibliothèques logicielles, officielles ou tierces.
Celles-ci peuvent être importées dans un script par une primitive import du type :
Les virtualenv Python servent à gérer pour chaque projet ses dépendances exactes, à l'inclusion des numéros de version des bibliothèques utilisées, et ce sans interférer avec d'autres projets.
On utilisera donc les virtualenv pour des questions de facilité, et parce qu'ils permettent de s'assurer de la pérennité d'un développement.
Vous pouvez installer virtualenv à l'aide de la commande :
La version `"_v1_django"` permet d'installer Django dans un virtualenv Python. Si vous avez installé Django et Virtualenv comme indiqué précédemment, l'installation devrait se faire sans retélécharger des bibliothèques Python depuis internet.
Elle suppose que vous installez toutes les bibliothèques avec `pip`, si ce n'était pas le cas, il faut éventuellement changer la variable `VENV` du `Makefile`, ou installer une version avec `pip3`.
Pour installer le virtualenv, Django, créer un projet et une application, tapez simplement la commande :
Pour l'**arrêter**, tapez la combinaison de touches`CTRL-C`.
Détaillons les étapes du Makefile :
- création du répertoire d'installation de l'environnement de développement, représenté par la variable `INSTALL_DIR` dans le Makefile ;
- création du virtualenv Python dans l'environnement de développement ;
- mise à jour de pip3 dans l'environnement de développement ;
- installation de Django ;
- création du projet, dont le nom est représenté par la variable `PROJECT_NAME` ;
- création de l'application `APP_NAME`.
Vous remarquerez que chacune des étapes ne modifie que le répertoire d'installation situé à l'intérieur du répertoire git, jamais des bibliothèques système.
Jusqu'ici, on n'a toujours pas écrit de code correspondant à notre application, seulement décrit une manière générale d'obtenir un projet Django d'équerre pour commencer. Il reste quelques étapes à connaître pour avancer dans le développement d'applications web avec Django sans que celui-ci se mette en travers de notre chemin.
Lors de la création d'un projet Django, certaines applications sont installées pour nous, par exemple l'interface d'administration. Celle-ci n'est pas migrée, opération qu'il faut réaliser pour pouvoir l'utiliser.
On a par ailleurs créé notre propre application, qui n'est pas non plus migrée.
Il est nécessaire d'effectuer les migrations des applications, car celles-ci peuvent entraîner une modification du modèle en base de données.
Obtenez le code de la version `_v2_migration` du projet git pour pouvoir migrer les applications du projet, et lancer le serveur Django de développement.
- les sources sont dans le répertoire mon\_django (nom du projet) ;
- la production est dans le répertoire sandbox ;
- les sources ont des liens sympboliques vers la production ;
- à la racine du projet se retrouvent éventuellement :
- la documentation ;
- la licence ;
- les tests (unitaires, intégration).
Cette organisation a pour but de **simplifier** le développement :
- le Makefile (et les scripts qu'il appelle) permet de construire et reconstruire le projet à l'aide d'une seule commande ;
- à chaque enregistrement d'une modification d'un fichier source sur disque, le serveur de développement Django redémarre avec la mise à jour, grâce aux liens symboliques vers les sources ;
- la production est séparée des sources ;
- le dépôt git peut être organisé en suivant les bonnes pratiques de développement Python :
- disposition de la documentation ;
- disposition des tests unitaires et intégration...
# Comparaison Django et Flask
Ça y est, on a enfin tout un environnement prêt pour le développement. Vous allez me dire "était-ce bien la peine de faire tout ça pour en arriver au même point ?" Je crois que oui.
- le code de Django est plus organisé que celui de Flask, ce qui procure un avantage sur le long terme :
- les vues et le contrôleur sont séparés ;
- Django incite à faire du développement de petites applications réutilisables au sein de plusieurs projets
- Django va permettre de s'interfacer facilement avec une base de données, ce qui fait qu'on a en fait de l'avance par rapport au cas où l'on serait restés avec Flask
- j'ai mis en place un système de construction avec les Makefiles qui permet de tester son application à l'aide d'une seule commande, comme pour Flask.
Je ne détaille pas les inconvénients de Django, il y en a un principal selon moi, la relative difficulté de le mettre en place, ce qui est fait par le système de construction logicielle avec Makefile.
Django fonctionne fondamentalement de la même manière que Flask pour le routage, mais il sépare les vues et le contrôleur :
- on utilise généralement le fichier `urls.py` pour décrire la liste des urls proposées par une applications :
- ces URL ne doivent pas se chevaucher, autrement une seule des URL serait prise en compte (la première rencontrée par Django) ;
- la liste des URL de tous les fichiers `urls.py` de toutes les applications constitue l'API backend offerte par votre projet Django ;
- on utilise le fichier `views.py` pour le code métier qui va recevoir les requêtes GET/POST HTTP ;
- on peut éventuellement créer d'autres modules Python pour du code spécifique ;
- on utilise le fichier `models.py` pour décrire les modèles des données de l'application, tels que ces données seront sauvegardées en base de données.
# Le développement avec Django
Maintenant que vous avez vu l'installation de Django en virtualenv Python, ainsi que la théorie sur la manière dont il faut organiser le code Python, allons voir quelques exemples simples.
Obtenez la version `_v3_application` du dépôt. Elle contient un simple "Hello World!" si le client demande la page`http://localhost:8000/`, et une simple indication "Not found" pour toutes les autres pages. Comme pour chanque étape de ce tutoriel, la commande :
permet de faire le café (enfin presque). Par rapport à l'étape précédente, on dispose désormais d'une application Django dont le code Python est importé.
En lisant le code,on s'aperçoit que son organisation est similaire à celle de Flask : d'un côté on route les urls, on utilise un ou plusieurs fichiers`urls.py` pour ce faire, et dans les vues du fichier`views.py` de chaque application du projet, on peut écrire le code à exécuter pour chaque requête.
Le routage des URL du projet (et de chacune des applications) est défini à l'aide de [regex](https://fr.wikipedia.org/wiki/Expression_r%C3%A9guli%C3%A8re) [Python](https://docs.python.org/fr/3.5/howto/regex.html). Je fait correspondre les URL suivantes :
La [page suivante](https://docs.djangoproject.com/fr/stable/topics/http/urls/#named-groups) de la documentation permet une utilisation avancée des URL de routage de l'application. On peut par exemple utiliser un champ de l'URL comme paramètre.
Je ne vous ai pas promis la lune mais presque, allons plus loin dans les fonctionnalités qui sont un des grands avantages de Django.
La version `_v4_template` permet d'utiliser les templates de Django. Je n'en fait qu'un usage très limité, je me limite à indiquer à Django où il doit aller chercher les fichiers de template correspondant au code HTML/CSS/JavaScript, servis par le serveur de développement, mais ce moteur de gabarits possède de nombreuses fonctionnalités, comme les variables, les tags, des boucles, des conditions...
La page accessible à l'URL par défaut `http://localhost:8000/` affiche le code du template`index.html` :
J'ai rajouté de manière explicite un paramètre optionnel : le dictionnaire vide `{}`. Il sert à préciser des variables Python à transmettre au moteur de gabarits.
Toutes les autres requêtes redirigent vers la page 404.
Une grande quantité d'applications web nécessite une base de données. Django propose un moyen simple pour s'interfacer avec une base de données sans nécessairement en connaître les subtilités, fournit des garanties qui permettent éventuellement de changer de moteur de base de données, et permet au développeur de manipuler les objets en base facilement.
La version `_v5_bdd` présente un exemple simple d'utilisation d'une base de données. Les URL suivantes sont valides :
-`http://localhost:8000/create/` : crée un objet en base de données ;
-`http://localhost:8000/delete/` : supprime tous les objets ;
-`http://localhost:8000/get_nb_objects/` : affiche le nombre d'objets en base de données.
**Attention**, celles-ci ne le sont pas, il manque un `/` à la fin :
-`http://localhost:8000/create` ;
-`http://localhost:8000/delete` ;
-`http://localhost:8000/get_nb_objects`.
Si vous vous demandez pourquoi l'exemple marche bien que tous les objets aient le même nom et la même valeur de booléen, c'est parce qu'ils se voient attribuer un identifiant entier automatique croissant si on ne définit pas d'attribut ayant une clef primaire, cf. la [documentation](https://docs.djangoproject.com/fr/stable/topics/db/models/#automatic-primary-key-fields).
Vous remarquerez l'utilisation de la primitive Django `include` dans le code, par rapport à la version `_v4_template`, qui permet de découper le routage vers les URL d'une application.
Django utilise la fonction`__init__` qui sert à construire des objets Python. La [documentation](https://docs.djangoproject.com/fr/stable/ref/models/instances/#creating-objects) explique comment attacher un constructeur aux objets sérialisés en base de données, plutôt que de recourir à une méthode`build` comme je m'y suis pris dans l'exemple `_v5_bdd`. L'exemple se trouve dans le code de la version`_v6_constructeur`.
# Pour aller plus loin
Je ferai peut-être une suite à ce tutoriel Django. Dans tous les cas, sachez que le point auquel nous sommes arrivés n'est pas suffisant ! En effet, on utilise toujours le serveur de développement de Django, qui n'est [pas fait pour être utilisé en production](https://docs.djangoproject.com/fr/1.11/intro/tutorial01/#the-development-server), entre autres :
> "(notre métier est le développement d’environnements Web, pas de serveurs Web)."
D'**autres éléments sont à considérer** durant et après la phase de développement :
- la mise en place d'un mécanisme de journalisation de l'application ;
- la mise en place d'un chien de garde permettant de s'assurer que le serveur (nginx, apache, ou autre) sert toujours l'application que vous avez écrite ;
- la mise en place d'une sauvegarde des données en base...
Il s'agit d'un travail d'administration système indispensable. À ce travail s'ajoute éventuellement celui de développer une interface web ou autres, si besoin est.
Je n'ai pas parlé des modules de Django. Dans la version `_v4_bdd`, on utilise la fonction Django`render`, qui permet de retourner une chaîne de caractères en temps que réponse HTTP. Cela diffère de Flask, qui permet de simplement retourner une chaîne de caractères. L'explication tient au fait que Django utilise l'objet request pour le passer aux modules Django, dans la fonction render.
Si vous êtes intéressés par le sujet, je vous conseille [cette page](https://docs.djangoproject.com/en/stable/topics/http/middleware/), qui décrit les interactions possibles sur une requête, ainsi que la base de leur fonctionnement.
Voilà un bon début de projet Django. Pour le réutiliser, n'oubliez pas :
- de **changer la clef API** située dans le fichier mon\_django/settings.py ;
- de respecter la licence GPLv3.
Vous pouvez également créer un répertoire `git` de zéro à partir d'un des tags du dépôt exemple. Pour cela, obtenez les sources du dépôt au tag que vous souhaitez :
Vous pouvez aussi garder le dépôt `git` en l'état, le script `del_tags.sh` permet de supprimer les tags commençant par`"_"`.
# Conclusion
Mon but ici n'est pas de prétendre que Django est meilleur que Flask, comme je l'ai indiqué au début de ce tutoriel, j'ai très peu touché à Flask. Flask est un prétexte pour moi pour montrer un des différents aspects de Django (le routage des requêtes). Par ailleurs, en lisant un peu sur le sujet, on s'aperçoit que beaucoup de modules peuvent être utilisés pour donner à Flask des capacités similaires à celles qui viennent avec Django, par exemple :
- une interface d'administration ;
- un module [ORM](https://fr.wikipedia.org/wiki/Mapping_objet-relationnel) pour s'interfacer avec une base de données...
Il y a donc des arguments en faveur de Flask par rapport à Django, par exemple :
- le code de Flask est composé de moins de lignes de code ;
- on peut choisir ce dont on a réellement besoin parmi des fonctionnalités offertes par la bibliothèque qu'on utilise...
Django, a de son côté :
- l'organisation générale d'un projet web :
- Django encourage à structurer son code ;
- Django suggère la division du code en applications ;
- il permet aux développeurs de travailler sur des applications différentes, ce qui facilite la collaboration ;
- il vient avec un moteur de templates ;
- il vient avec un ORM...
Cette comparaison n'est évidemment pas exhaustive, mais permet de se rendre compte des convergences et divergences de philosophie de ses deux projets.
Vous voilà parés pour démarrer ! J'espère que ce tutoriel vous a été utile. Pour ma part, je trouve que Django est très sympathique à utiliser, sa documentation est facile à prendre en main pour un usage débutant, même si elle est touffue. Enfin sachez que raspbeguy et moi-même avons quelques projets web (parmi lesquels [clickstart](/posts/mon-nouveau-projet-dampleur/), et Hashtagueule Express) qui utiliseront peut-être cette technologie.
Bonne journée et bon développement Python/Django !
_Motius_
PS : après avoir commencé cet article, je suis tombé sur [celui-ci](http://stackabuse.com/flask-vs-django/), en anglais. Je tiens à le mentionner car la majorité des articles Flask vs Django sont théoriques (souvent des descriptions fonctionnelles, assez intéressantes pour se familiariser rapidement avec les deux projets), mais je n'avais pas vu (ni vraiment cherché) d'article les comparant en mettant la main dans le code.