Hey salut, bienvenue dans ce tutoriel sur Django. Ce tutoriel est le premier qui va parler de Django sur Kaherecode, pourtant je suis un très grand fan de ce puissant framework, mais plus d'un an après nous voilà.
Dans ce tutoriel, nous allons développer une application simple pour une communauté de développeurs, l'idée elle est simple, on a une page sur laquelle on liste les membres de la communauté avec leurs informations et un formulaire pour permettre à une personne d'adhérer à la communauté. L'objectif c'est qu'on puisse faire un peu le tour des fonctionnalités que nous offrent Django pour pouvoir le prendre en main, nous allons donc parler des routes, des vues, comment traiter un formulaire, les fichiers statiques, le puissant espace d'administration, interagir avec une base de données, ... On va s'amuser je te l'assure, personnellement j'ai kiffer travailler sur la démo. Et tu pourras faire de même pour ta communauté locale par exemple, la pratique est le seul secret dans ce domaine. Ce tutoriel sera en deux parties pour éviter qu'il soit long, ici nous allons parler de l'installation de Django, des routes et vues et templates.
Avant de commencer, il faut savoir que Django est un framework Python, et je suis du genre à dire que pour apprendre un framework, il faut d'abord connaître le langage dans lequel il est écrit. Il faut donc avoir une bonne connaissance du Python, parce que nous n'allons pas écrire du Django, mais plutôt du code Python. Et pour faire du Django, il faut avoir une connaissance des classes en Python, des listes et dictionnaires.
Comme nous l'avons dit, Django est un framework Python, c'est le framework web le plus populaire de Python et il est suivi de près par le micro-framework Flask qui est aussi très pratique et dont je parlais dans un précédent tutoriel. Nous allons donc tout de suite commencer par installer Django.
Installation
Avant d'installer Django, nous allons d'abord créer un environnement virtuel pour notre projet. Il faut toujours créer un environnement virtuel pour vos projets Python, cela vous permettra d'encapsuler toutes les dépendances de votre application pour éviter des conflits avec d'autres projets qu'il y a sur votre ordinateur.
J'utilise la version 3 de Python et toi aussi sûrement, si ce n'est pas le cas, il faut l'installer à partir du site officiel.
Pour créer un environnement virtuel, je vais utiliser le module venv
qui vient avec Python 3, il faut d'abord créer un dossier pour ton projet, puis place toi dans ce dossier et crée l'environnement virtuel:
$ mkdir django_community_app && cd django_community_app
$ python3 -m venv env
Un dossier env
sera créer dans le répertoire, il faut ensuite activer l'environnement avec:
$ source env/bin/activate
Il faudra faire ça à chaque que tu veux travailler sur ton projet pour installer des dépendances ou exécuter ton application.
Maintenant avec l'environnement virtuel activer, on peut installer Django:
$ pip install django
Une fois l'installation terminer, tu peux vérifier la version installer avec:
$ python -m django --version
3.0.8
La version que j'utilise moi est la 3.0.8
, ta version peut être différente de la mienne.
Nous pouvons maintenant créer un projet Django avec la commande django-admin
:
$ django-admin startproject community_app
Et voilà, le projet community_app
vient d'être créé dans le dossier courant. Si tu listes la liste des dossiers, tu verras qu'un nouveau dossier community_app
a été créé, nous allons travailler dans ce dossier. Voici la structure que nous avons actuellement:
community_app/
community_app/
asgi.py
__init__.py
settings.py
urls.py
wsgi.py
manage.py
- le premier dossier
community_app
, c'est le dossier qui contient le projet, tu peux le renommer sans problème - le dossier
community_app
en dessous, c'est le package python qui représente notre projet community_app/asgi.py
est le point d'entrée pour les serveurs ASGI comme Uvicorn, ...community_app/__init__.py
définit le dossiercommunity_app
comme un package pythoncommunity_app/settings.py
est le fichier de configuration de notre projet django- community_app/urls.py est le fichier dans lequel nous définirons les routes de notre application
community_app/wsgi.py
est le point d'entrée pour les serveurs WSGI comme Gunicorn, ...manage.py
est l'utilitaire en ligne de commande qui nous permet d'interagir avec notre projet Django
Nous pouvons maintenant lancer le serveur de développement pour voir notre projet en live:
$ python manage.py runserver
Pour l'instant ne pense pas au texte en rouge, notre application est accessible à l'adresse http://127.0.0.1:8000
Voilà, nous sommes maintenant prêt à aller plus loin avec Django.
Créer une application
Maintenant que nous avons un projet Django, il nous faut créer une application.
Un projet Django est un ensemble de plusieurs autres applications. Une application est en quelque sorte un package qui fait une tâche spécifique comme la gestion des membres par exemple, un forum ou encore un blog. Toutes ces 3 apps différentes peuvent être présentes dans notre projet Django. Et l'idée avec Django c'est que tu pourras après extraire ces applications pour pouvoir les réutiliser dans un autre projet. Si je développe une application blog
pour mon projet community_app
, je vais pouvoir l'exporter pour l'utiliser dans mon portfolio. Une application va encapsuler tout les models, les vues et routes nécessaires à son fonctionnement.
Nous allons créer une application members
pour la gestion des membres de notre communauté. Pour cela, il faut exécuter la commande:
$ python manage.py startapp members
Il faut activer l'environnement virtuel et te placer dans le même dossier que le fichier manage.py
avant d'exécuter cette commande.
Un dossier members
vient d'être créé. Ce dossier va contenir l'application members
.
Il faut ensuite ajouter l'application qui vient d'être créé dans community_app/settings.py
:
# community_app/settings.py
"""
Django settings for community_app project.
"""
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'members',
]
# ...
Dans la liste ISTALLED_APPS
, j'ajoute le nom de ma nouvelle application.
Hello World!
Alors le fameux Hello World!, il faut vraiment passer par là. Nous allons faire une page web qui affiche un message Hello World!
Pour commencer, il faut d'abord créer une vue. Dans une application, les vues sont défini par des fonctions dans le fichier views.py
, il faut donc modifier ce fichier comme ceci:
# members/views.py
from django.http import HttpResponse
# Create your views here.
def hello_world(request):
return HttpResponse('Hello World!')
On a une vue simple pour l'instant, qui retourne juste du texte avec la classe HttpResponse
.
Il faut ensuite créer une route qui pointe sur cette vue. Encore une fois, dans une application, les routes sont définis dans un fichier urls.py
qui n'existe pas pour l'instant, il faut donc le créer dans le dossier members
et y mettre le contenu suivant:
# members/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('hello/', views.hello_world, name='hello'),
]
Là aussi c'est plutôt simple, on importe la méthode path
de django.urls
, ensuite nous importons le module views
que nous venons juste de créer, on crée les routes dans une liste urlpatterns
et on définit chaque route avec la fonction path()
.
Prochaine et dernière étape, il faut définir nos routes dans le fichier de routes principal. Le fichier principal pour les routes de notre projet c'est community_app/urls.py
. Le fichier members/urls.py
définit juste les routes au sein de l'application members
.
A chaque fois que nous créons donc une nouvelle application il faut importer son fichier urls.py
dans le fichier principal. Il faut donc modifier le fichier community_app/urls.py
comme ceci:
# community_app/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('members/', include('members.urls')),
path('admin/', admin.site.urls),
]
On ajoute les routes de l'application members
avec include('members.urls')
et la route pour y accéder est members/
(toujours mettre le slash à la fin pour éviter de mauvaises surprises).
Si tu navigues maintenant sur le lien http://127.0.0.1:8000/members/hello/, tu as une page qui s'affiche avec le message Hello World!
Voilà ce qu'il faut pour faire une application web avec django. Mais on ne va pas s'arrêter en si bon chemin.
Routes
Nous avons déjà vu comment créer des routes dans la section précédente. Nous allons maintenant ajouter les routes de notre projet.
Nous aurons besoin de 2 routes, une pour la page d'accueil où sera afficher la liste de tous les membres, et une autre pour afficher les détails d'un membre.
Nous allons commencer par ajouter les deux fonctions pour les vues dans le fichier members/views.py
:
# members/views.py
from django.http import HttpResponse
# Create your views here.
def homepage(request):
return HttpResponse('<h1>Bienvenue sur ma communauté de devs.</h1>')
def member_view(request, member_id):
return HttpResponse('<h1>Affichage du membre numéro {}</h1>'.format(member_id))
Pour l'instant nous retournons toujours de simple texte HTML. La fonction member_view()
prend un deuxième paramètre qui est l'identifiant du membre à afficher.
Nous allons ensuite modifier le fichier members/urls.py
pour pointer sur ses vues:
# members/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.homepage, name='homepage'),
path('member/<int:member_id>/', views.member_view, name='member')
]
La première route est plutôt simple, la route c'est une chaîne vide.
La route pour afficher un membre a besoin d'un paramètre entier, et le member_id
dans la vue vient d'ici au fait. La route va donc se présenter comme /member/4/
, /member/14/
, ... mais pas /member/1b
ou /member/aliou
, si tu essaies avec ces deux derniers, tu auras une erreur 404
qui dit que la page n'existe pas.
Ici nous disons que c'est un type entier, mais tu peux utiliser d'autres types comme les chaînes de caractère, uuid, les expressions régulières, ...
Tu pourras en savoir plus sur la documentation.
Actuellement pour accéder à la page d'accueil il faut faire http://127.0.0.1:8000/members/, mais j'aimerais que ce soit tout simplement http://127.0.0.1:8000, il faut donc modifier le fichier community_app/urls.py
:
# community_app/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('members.urls')),
path('admin/', admin.site.urls),
]
Et voilà, nous avons les deux routes dont on a besoin. Nous allons maintenant créer les vues qui vont avec ces routes.
Templates
Jusque là, nous retournons simplement du texte HTML, on peut bien continuer ainsi si nos pages web ne contiennent qu'une ou deux balises HTML, sinon, il va falloir créer des pages HTML et appeler ces pages pour chaque route.
Nous allons commencer par créer la page d'accueil. Avec django, chaque application doit définir un dossier templates
dans lequel les templates de l'application seront défini. Dans le dossier members
, il faut donc créer un dossier templates
et à l'intérieur de ce dossier, nous allons encore créer un autre sous dossier members
, comme le nom de l'application.
On aura donc une architecture comme ça pour l'application members
:
members/
migrations/
...
templates/
members/
index.html
admin.py
apps.py
__init__.py
models.py
tests.py
urls.py
views.py
Nous allons donc créer nos templates dans members/templates/members
, vas y et crée un fichier index.html
puis mets y le contenu suivant:
{# members/templates/members/index.html #}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Django Community App</title>
</head>
<body>
<h1>Hello, bienvenue sur mon projet Django!</h1>
</body>
</html>
Et nous voulons que cette page soit retourner à chaque fois que l'utilisateur arrive sur la page d'accueil, nous allons donc modifier le fichier members/views.py
pour appeler ce fichier:
# members/views.py
from django.shortcuts import render
from django.http import HttpResponse
def homepage(request):
return render(request, 'members/index.html')
# ...
Je modifie juste la méthode homepage
qui renvoie maintenant la page HTML que nous venons de créer.
Si tu accèdes maintenant à la page d'accueil http://127.0.0.1:8000, tu as une page HTML qui est renvoyer.
Tu peux mettre le contenu HTML que tu souhaites, cela dépend de toi.
Nous allons par la même occasion créer le deuxième fichier HTML, je vais l'appeler member_view.html
et le placer dans members/templates/members
:
{# members/templates/members/member_view.html #}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Membre Numéro {{ member_id }}</title>
</head>
<body>
<h1>Membre Numéro {{ member_id }}</h1>
</body>
</html>
Et aussi modifier la vue pour afficher cette page:
# members/views.py
from django.shortcuts import render
def homepage(request):
return render(request, 'members/index.html')
def member_view(request, member_id):
return render(request, 'members/member_view.html', locals())
Et cette fois aussi si tu accèdes à la route http://127.0.0.1:8000/member/4 tu as cette page:
Juste une petite explication, dans la fonction member_view()
, on envoie un troisième paramètre locals()
à la fonction render()
, ce troisième paramètre nous permet d'envoyer toutes les variables de la vue au template, ainsi dans le template, tu pourras accéder à ces variables à travers leur nom. Si tu remarques bien dans le template member_view.html
, on affiche la variable member_id
avec {{ member_id }}
.
Django utilise Jinja2 comme moteur de templates, tu peux en savoir plus sur la documentation de Django ou aussi de Jinja2.
Héritage de templates
Quand on travaille sur un projet web, généralement les pages web ont le même layout. Le header
reste le même sur toutes les pages, le footer
aussi. Sur un projet HTML simple, nous allons répéter le même code sur toutes les pages, mais nous ne sommes sur un projet HTML simple ici. Nous allons donc créer un fichier HTML qui va nous servir de layout
et qui va définir tout ce que nos pages ont en commun, ça va être le fichier mère, tous nos templates vont ensuite hériter de ce fichier, c'est comme l'héritage en Programmation Orienté Objet.
Je vais donc commencer par créer un dossier templates à la racine de mon projet et ensuite créer dans ce dossier un fichier layout.html
:
{# templates/layout.html #}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Django Community App - {% block title %}{% endblock title %}</title>
</head>
<body>
<header>
<h1>Page header</h1>
</header>
{% block content %}{% endblock content %}
<footer>
<h1>Page footer</h1>
</footer>
</body>
</html>
Je définis la structure d'un fichier HTML tout simplement avec un header
et footer
. En plus de cela, je définis deux blocs avec {% block name %}{% endblock name %}
, les templates qui hériteront de ce template vont écrire leur contenu dans ces deux blocs.
Il faut ensuite définir ce dossier dans la liste des TEMPLATES
de notre projet vu qu'il ne fait pas parti d'une application, dans le fichier community_app/settings.py
:
# community_app/settings.py
# ...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# ...
J'ai juste modifier la clé DIRS
du dictionnaire.
Je vais maintenant faire hériter le templates index.html
de ce fichier:
{# members/templates/members/index.html #}
{% extends 'layout.html' %}
{% block title %}Accueil{% endblock title %}
{% block content %}
<p>Bienvenue sur mon projet Django!</p>
{% endblock content %}
Et maintenant la page d'accueil ressemble à ceci:
Tout le contenu de ta page sera écrit dans un bloc au risque de ne pas s'afficher.
Et le fichier member_view.html
aussi:
{# members/templates/members/member_view.html #}
{% extends 'layout.html' %}
{% block title %}Membre numéro {{ member_id }}{% endblock title %}
{% block content %}
<p>Membre numéro {{ member_id }}</p>
{% endblock content %}
Fichiers statiques
Les fichiers statiques sont les fichiers CSS, JS, images, ... que nous ajoutons à nos pages web. Comme pour les templates, nous allons avoir nos fichiers statiques dans une application si elles sont seulement utilisés par cette application, ou dans un dossier static
à la racine du projet si le fichier est partagés par toutes les applications du projet comme le fichier de style par exemple.
Nous allons donc créer un dossier static
à la racine du projet et à l'intérieur un autre dossier css
puis un fichier style.css
dans le dossier css
:
/* static/css/style.css */
body {
background-color: #0c4b33;
color: #fff;
}
Il faut ensuite déclarer ce dossier dans community_app/settings.py
en ajoutant ce code à la fin du fichier:
# community_app/settings.py
# ...
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
Et appeler le fichier style.css
dans layout.html
:
{# templates/layout.html #}
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Django Community App - {% block title %}{% endblock title %}</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<header>
<h1>Page header</h1>
</header>
{% block content %}{% endblock content %}
<footer>
<h1>Page footer</h1>
</footer>
</body>
</html>
Je commence d'abord par charger le module static
avec {% load static %}
, puis je l'utilise sur la ligne 8 avec {% static 'css/style.css' %}
.
Et si tu actualises la page d'accueil, tu as du texte blanc sur un fond vert un peu moche je l'avoue, mais l'idée est là.
Voilà, nous savons maintenant créer des routes, les rattacher à une vue et retourner une page HTML.
J'ai apporté quelques modifications pour les pages HTML et le style, j'ai utilisé TailwindCSS pour le design, je ne peux pas te partager ici directement le code parce qu'il est un peu trop long, tu peux donc te rendre sur le dépôt de ce projet pour accéder au codes source. Voici le rendu final que j'ai obtenu.
Nous allons nous limiter ici pour cette partie, dans la prochaine partie, nous allons créer nos modèles et enregistrer les membres dans une base de données. D'ici là, je te propose de faire le tour de tout ceux sur quoi nous avons travailler dans ce tutoriel, seul la pratique compte. Si tu as des questions n'hésite pas à me les poser dans les commentaires ci-dessous ou à m'écrire sur le chat discord de Kaherecode ou je suis plus actif. Merci à bientôt.
Participe à la discussion