Actions

Cours

Initiation à Django

De GBLL, TAL, ALAO, etc.

Django est un framework python qui vous permet de rapidement créer un site web, une application web ou une API.

[Site officiel de Django]

Création d'un environnement virtuel

Nous allons utiliser Django dans un environnement virtuel. Tous les modules que vous installerez pour ce projet ne seront donc pas installés sur votre ordinateur, mais seulement dans cet environnement virtuel. Cela permet de ne pas encombrer votre machine avec un tas de modules qui ne servent que sur quelques projets, et cela simplifie l'installation des dépendances sur un serveur distant.

Il existe plusieurs outils pour créer un environnement virtuel, nous allons utiliser pipenv.

  1. Installer pipenv sur votre machine : pip install pipenv ou python -m pip install pipenv.
    Vous pouvez utilisez également python3 ou pip3.
  2. Créez un répertoire où vous voulez sur votre machine, nous travaillerons dedans à partir de là :
    • mkdir monDossier
    • cd monDossier
  3. Initialisez un environnement virtuel dans ce dossier : pipenv shell ou python -m pipenv shell.
    C'est la commande pour activer l'environnement virtuel si il existe, sinon il le crée. Comme c'est la première fois ici, il le crée.
    Vous verrez le message suivant : Launching subshell in virtual environment.... Puis vous entrez automatiquement dans l'environnement.
    Quand vous êtes dans un environnement virtuel, vous pouvez voir le nom de l'environnement entre parenthèses devant votre ligne de commande : (monDossier) sylvain@chistoyenebo:~/temp/monDossier$.
  4. Pour sortir de l'environnement virtuel : exit ou ctrl+C.
  5. Pour entrer dans l'environnement virtuel : pipenv shell ou python -m pipenv shell
  6. Pour voir quels modules sont installés dans votre environnement : pip freeze.
    Si vous n'avez encore rien installé, il n'y a rien. Notez que tous les modules installés sur votre ordinateur sont accessibles depuis cet environnement (mais pas le contraire).

Premiers pas avec Django

Notez que tout ce qui suit peut être fait directement sur votre ordinateur, pas forcément dans un environnement virtuel. Mais je vous conseille de prendre l'habitude d'utiliser un environnement virtuel quand vous travaillez sur un projet avec pas mal de modules à installer.

Installer Django et initialiser un nouveau projet

  1. Une fois dans votre environnement virtuel, installez Django : pip install Django
  2. Initialisez un nouveau projet Django : django-admin startproject monProjet .. Un dossier de configuration a été créé, il contient le paramétrage de votre projet (notamment settings.py, urls.py), et un fichier manage.py se trouve à la racine de votre projet, c'est ce fichier qui contient la plupart des fonctions de Django qui permettrons de créer des apps, gérer les modèles, faire tourner le serveur etc.
  3. Vous pouvez d'ores et déjà lancer votre serveur : python manage.py runserver, et accéder à la page par défaut de Django (comme rien n'est encore écrit) en vous rendant à l'adresse http://127.0.0.1:8000/ ou http://localhost:8000/. Ctrl+C pour arrêter le serveur.

Créer une app

Votre projet Django peut contenir plusieurs apps (par exemple une pour gérer les pages du sites, une autre pour gérer les utilisateurs (authentification, mails etc.), une API requêtable par d'autres programmes etc.). Dans ce cours, on va en créer une seule, ça suffira.

  1. Créer une nouvelle app (ex. "myApp"): à la racine de votre projet (là où il y a manage.py) python manage.py startapp myApp
  2. Ajouter l'application à votre projet : dans le dossier du projet, ouvrez settings.py et ajoutez votre app dans INSTALLED_APPS (ici, 'monAppli').
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'myApp',
    ]
    

Vous trouverez un nouveau répertoire avec les fichiers de votre app, notamment views.py où on écrira les différentes actions à faire en fonction des requêtes ; ou encore models.py où on définira nos classes d'objets.

Créer les répertoires "templates" pour vos html et "static" pour vos css, js, images...

  1. Nous allons ranger tous les fichiers html dans un répertoire appelé "templates". Créez-le à la racine du projet, puis éditez le fichier settings.py (dans le dossier de paramétrage du projet) : ajoutez import os au début du fichier, puis complétez TEMPLATES le chemin vers templates :
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')],
            'APP_DIRS': True,
            'OPTIONS': {
            ...
    
  2. Tous les fichiers css, js, les images et autres média seront quant à eux stockés dans un répertoire appelé "static". Comme pour templates, créez ce répertoire à la racine du projet, puis éditez settings.py :
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]


À ce stade, le paramétrage minimum est fait, il ne vous reste plus qu'à créer des views (actions du serveur) et des templates (affichage pour le client), et à appeler ces views dans urls.py.

Voilà à quoi devrait ressembler votre répertoire :

.
├── db.sqlite3
├── manage.py
├── monProjet
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── myApp
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── Pipfile
├── static
└── templates

Première view

On va commencer par afficher une page html en page d'accueil de notre site.

  1. Créer un template html qui nous servira de page d'accueil. Dans templates/, créez un fichier home.html et mettez du contenu html temporaire dedans (ex. <h1>Bienvenue !</h1>).
  2. Dans views.py, définissez une nouvelle view qui affichera simplement ce template :
    from django.shortcuts import render
    
    def home(request):
        return render(request, 'home.html')
    
  3. Il ne reste qu'à indiquer à quelle url on veut afficher cette page, ici c'est une page d'accueil, donc à la racine : dans urls.py ajoutez :
    from myApp import views as myApp
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', myApp.home),
    ]
    

Retournez sur votre navigateur et rafraîchissez la page, vous devriez voir votre page html. (le serveur doit tourner)

View avec des variables

Faisons une nouvelle view qui affiche des variables.

  1. Dans views.py, définissez une nouvelle view qui transmettra des variables à un nouveau template :
    def variables(request):
        nom = "Édouard"
        hobbies = ["ping pong", "lecture", "musique"]
    
        return render(request, 'variables.html', {"nom":nom, "hobbies":hobbies})
    
  2. Créer un nouveau template html variables.html et appelez les variables de la manière suivante :
    <p>Mon nom est {{ nom }}.</p>
    
    <p>Voici mes hobbies :</p>
    <ul>
        {% for hobbie in hobbies %}
        <li>{{ hobbie }}</li>
        {% endfor %}
    </ul>
    
    <p>Mais j'aime particulièrement le {{ hobbies.0 }} !</p>
    
  3. Indiquez à quelle url on veut afficher cette page, par exemple variables/ : dans urls.py ajoutez :
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', myApp.home),
        path('variables/', myApp.variables),
    ]
    

Retournez sur votre navigateur et affichez http://127.0.0.1:8000/variables/

Let's do something useful

Bon, faisons un truc qui ressemble un peu à quelque chose, voulez-vous ?

a) du style

On va utiliser des css. Vous pouvez utiliser une css maison, mais je vous suggère vivement de profiter de ce que la communauté nous offre : Bootstrap CSS. Vous pouvez ensuite compléter en ajoutant une css perso qui ajoute ou écrase certains styles de bootstrap.

Le site de Bootstrap CSS v5 : https://getbootstrap.com/docs/5.0/getting-started/introduction/ Il s'agit de styles tous prêts que vous pouvez appelez depuis votre html, ça fait gagner beaucoup de temps, et le résultat est plus responsive.

On va même utiliser Bootswatch, qui propose des thèmes de site entier : https://bootswatch.com/

Exemple : par exemple, choisissons ce thème https://bootswatch.com/sketchy/ , en haut de la page, cliquez sur Sketchy puis téléchargez bootstrap.min.css, et mettez-la dans votre projet, dans static/styles/ par exemple.

Dans home.html, on va écrire un fichier html classique et appeler la css, et ajouter un bout de code d'un élément au hasard, par exemple une card (pour chaque élément sur Bootswatch, vous avez le code source à copier/coller) :

{% load static %}
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" type="text/css" href="{% static 'styles/bootstrap.min.css' %}">
</head>
<body>
    <div class="container">
        <h1>Bienvenue !</h1>
        <div class="card text-white bg-dark mb-3" style="max-width: 20rem;">
            <div class="card-header">Un élément pris au hasard</div>
            <div class="card-body">
            <h4 class="card-title">Dark card title</h4>
            <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
            </div>
        </div>
    </div>
</body>
</html>

b) de la structure

Mettons que vous voulez mettre une navbar sur votre site, mais que vous voulez que cette navbar s'affiche sur toutes les pages (pas seulement home.html). Ce que nous permet Django (comme bien d'autres frameworks), c'est d'importer des bouts de html dans un html parent commun à plusieurs pages. Ici, on voudrait une base commune base.html avec le header, l'appel à la css, la navbar; et appeler ensuite la page du site de notre choix (variables/ ou une autre).

  1. Créez un fichier base.html dans templates/, contenant la balise html avec le header, et un body avec une navbar :
{% load static %}
{% load static %}
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" type="text/css" href="{% static 'styles/bootstrap.min.css' %}">
</head>
<body>

    <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
        <div class="container-fluid">
        <a class="navbar-brand" href="#">myApp</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
    
        <div class="collapse navbar-collapse" id="navbarColor01">
            <ul class="navbar-nav me-auto">
            <li class="nav-item">
                <a class="nav-link active" href="/">Home
                <span class="visually-hidden">(current)</span>
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="membres/">Membres</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Articles</a>
            </li>
            <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Dropdown</a>
                <div class="dropdown-menu">
                <a class="dropdown-item" href="#">Action</a>
                <a class="dropdown-item" href="#">Another action</a>
                <a class="dropdown-item" href="#">Something else here</a>
                <div class="dropdown-divider"></div>
                <a class="dropdown-item" href="#">Separated link</a>
                </div>
            </li>
            </ul>
            <form class="d-flex">
            <input class="form-control me-sm-2" type="text" placeholder="Search">
            <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
            </form>
        </div>
        </div>
    </nav>
  
    <div class="container">
        {% block content %}{% endblock %}
    </div>

</body>
</html>