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 :
 1 {% load static %}
 2 <!DOCTYPE html>
 3 <html lang="fr">
 4 <head>
 5     <meta charset="UTF-8">
 6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 7     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 8     <title>Document</title>
 9     <link rel="stylesheet" type="text/css" href="{% static 'styles/bootstrap.min.css' %}">
10 </head>
11 <body>
12 
13     <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
14         <div class="container-fluid">
15         <a class="navbar-brand" href="#">myApp</a>
16         <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
17             <span class="navbar-toggler-icon"></span>
18         </button>
19     
20         <div class="collapse navbar-collapse" id="navbarColor01">
21             <ul class="navbar-nav me-auto">
22             <li class="nav-item">
23                 <a class="nav-link active" href="/">Home
24                 <span class="visually-hidden">(current)</span>
25                 </a>
26             </li>
27             <li class="nav-item">
28                 <a class="nav-link" href="/variables/">Variables</a>
29             </li>
30             <li class="nav-item">
31                 <a class="nav-link" href="#">Articles</a>
32             </li>
33             <li class="nav-item dropdown">
34                 <a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Dropdown</a>
35                 <div class="dropdown-menu">
36                 <a class="dropdown-item" href="#">Action</a>
37                 <a class="dropdown-item" href="#">Another action</a>
38                 <a class="dropdown-item" href="#">Something else here</a>
39                 <div class="dropdown-divider"></div>
40                 <a class="dropdown-item" href="#">Separated link</a>
41                 </div>
42             </li>
43             </ul>
44             <form class="d-flex">
45             <input class="form-control me-sm-2" type="text" placeholder="Search">
46             <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
47             </form>
48         </div>
49         </div>
50     </nav>
51   
52     <div class="container">
53         {% block content %}{% endblock %}
54     </div>
55 
56 </body>
57 </html>


Le contenu des pages du site apparaîtra dans le block content (ligne 53).

  1. Remplacez le contenu de home.html par :
    {% extends "base.html" %}
    
    {% block content %}
     <h1>Bienvenue !</h1>
    {% endblock %}
    
  2. Éditez variables.html de la même façon:
    {% extends "base.html" %}
    
    {% block content %}
    <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>
    {% endblock %}
    

Vous avez maintenant les bases pour vous faire un petit site ! Essayez de créer d'autres pages, avec d'autres éléments bootstrap et d'autres variables.

c) aller plus loin avec les variables de template

Boucles

Boucler sur une liste d'objets :

(views.py)

membres = [
        {"nom":"Dupond", "prenom":"Sophie"},
        {"nom":"Hache", "prenom":"Anne"},
        {"nom":"Von Ergstadt", "prenom":"Émile"},
        {"nom":"Dupuit", "prenom":"Alex"},
]

(template html)

{% for membre in membres %}
        <p>{{ membre.nom }}, {{ membre.prenom }}</p>
{% endfor %}

Boucler sur un dictionnaire :

(views.py)

bigmac = {
        "Énergie": "504kcal",
        "Matières grasses": "25g",
        "Dont acides gras saturés": "9,2g",
        "Sucres": "8,2g",
        "Sel": "2,2g"
}

(template html)

{% for nom, val in bigmac.items %}
    <p>{{ nom }} : {{ val }}</p>
{% endfor %}

Plus d'infos : https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#for

If statement

(views.py)

langue = "en"

(template html)

{% if langue == "fr" %}
    <p>Quelque chose en français...</p>
{% elif langue == "en" %}
    <p>Something in English...</p>
{% else %}
    <p>{% lorem 2 p %}</p>
{% endif %}

Tous les opérateurs classiques fonctionnent.

Plus d'infos : https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#if

Formater une date

(views.py)

import datetime
date_birthday = datetime.date(1992,12,24)

(template html)

{{ date_birthday | date:"l, d F Y"}}

Plus d'infos : https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#date

Par défaut votre serveur Django est sur Greenwich et en anglais, vous pouvez le passer à l'heure française et en français dans settings.py, changez les lignes suivantes :

LANGUAGE_CODE = 'fr'
TIME_ZONE = 'Europe/Paris'

Analyse morphosyntaxique avec Spacy

Dans ce cours nous allons utiliser l'analyseur morphosyntaxique Spacy : https://spacy.io/

Installation de Spacy

  1. Installez Spacy dans votre environnement virtuel : pip install -U spacy
  2. Puis installez un modèle de langue, par exemple fr_core_news_md (vous trouverez plein de modèles ici: https://spacy.io/models/fr) : python -m spacy download fr_core_news_md

Plus d'infos pour l'installation de Spacy si besoin : https://spacy.io/usage

Premiers pas avec Spacy

Commençons par faire tourner Spacy dans un petit script Python indépendant. Créez un petit script de test testSpacy.py, où vous voulez dans votre projet, par défaut à la racine :

import spacy
nlp = spacy.load("fr_core_news_md")

doc = nlp("Ceci est une phrase d'exemple.")
print(doc.text)
for token in doc:
    print(token.text, token.lemma_, token.pos_, token.morph.to_dict(), token.dep_, token.shape_)

Vous devriez obtenir ce résultat :

Ceci est une phrase d'exemple.
Ceci ceci PRON {'Number': 'Sing', 'PronType': 'Dem'} nsubj Xxxx
est être AUX {'Mood': 'Ind', 'Number': 'Sing', 'Person': '3', 'Tense': 'Pres', 'VerbForm': 'Fin'} cop xxx
une un DET {'Definite': 'Ind', 'Gender': 'Fem', 'Number': 'Sing', 'PronType': 'Art'} det xxx
phrase phrase NOUN {'Gender': 'Fem', 'Number': 'Sing'} ROOT xxxx
d' de ADP {} case x'
exemple exemple NOUN {'Gender': 'Masc', 'Number': 'Sing'} nmod xxxx
. . PUNCT {} punct .


Notez que le chargement du modèle de langue peut prendre quelques secondes lorsqu'on exécute le script. Ce temps de chargement aura lieu lorsque vous démarrerez le serveur Django, quand vous utiliserez Spacy dans votre appli Django.


Spacy permet également de visualiser l'arbre des dépendances, et aussi d'accéder aux word embeddings et mesurer la distance entre des token, des phrases ou le texte !

Utilisation de Spacy dans votre appli Django

Il vous suffit de mettre le code python précédent dans views.py. Importez spacy et chargez le modèle de langue en tête du fichier, puis analysez ce que vous voulez dans une view de votre appli. Vous pouvez alors injecter l'output de l'analyse morphosyntaxique sur une page du site.

Requêter Spacy depuis le client

À titre d'exemple, dans ce cours, nous proposons la fonctionnalité suivante : l'utilisateur du site entre du texte brut à analyser, il appuie sur un bouton et l'appli envoie ce texte vers le serveur, le texte est analysé par Spacy dans une view de l'appli qui renvoie enfin le résultat au client.

Interface utilisateur

Commençons par ajouter une zone d'input de texte dans une des pages de l'application, par exemple home.html.

L'input de l'utilisateur se fera ici dans une textarea (ligne 15), le bouton permettra d'exécuter une fonction appelée ici sendText() (ligne 16). Le résultat, enfin, sera affiché dans la div outText (ligne 18).

 1 {% extends "base.html" %}
 2 {% load static %}
 3 
 4 {% block content %}
 5 <h1>Bienvenue !</h1>
 6 <div class="card text-white bg-primary mb-3" style="max-width: 20rem;">
 7     <div class="card-header">Header</div>
 8     <div class="card-body">
 9       <h4 class="card-title">Primary card title</h4>
10       <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>
11     </div>
12 </div>
13 
14 <div class="d-flex">
15     <textarea id="inText" cols="40"></textarea>
16     <button type="button" class="btn btn-primary" onclick="sendText()">Analyser !</button>
17 </div>
18 <div id="outText"></div>
19 
20 {% endblock %}

Lier un fichier javascript à la page html

On pourrait directement rédiger le code de la fonction sendText() dans une balise <script> à la fin du body, mais prenons l'habitude de rédiger les scripts js dans un fichier dédié.

Nous mettrons tous nos scripts js dans un dossier "scripts" dans le répertoire "static". Nous mettrons le code associé à la page home.html dans le fichier static/scripts/home.js.

Commençons par y mettre juste un console.log() qui indiquera que le script est bien chargé, et un autre console.log() dans la définition de la fonction sendText():

console.log('Le script est bien chargé!');

function sendText() {
  console.log("L'utilisateur a cliqué sur le bouton !");
}

Comme le script home.js sera exécuté que depuis la page home.html, il vaut mieux l'appeler depuis home.html et non base.html, sinon il serait téléchargé par le client pour chaque page du site. Base.html contient déjà un block "content", de la même manière, créons un block javascript à l'endroit où on veut que le code apparaisse, dans notre cas, juste avant la fermeture du body.

Dans base.html :

      (...)
    </div>
  </nav>
  
  <div class="container">
    {% block content %}{% endblock %}
  </div>

  {% block javascript %}{% endblock %}
</body>
</html>

Puis dans home.html, appeler le script dans ce block dédié (penser à ajouter le tag

{% load static %}

au début du fichier).

{% extends "base.html" %}
{% load static %}

{% block content %}
<h1>Bienvenue !</h1>
<div class="card text-white bg-primary mb-3" style="max-width: 20rem;">
    <div class="card-header">Header</div>
    <div class="card-body">
      <h4 class="card-title">Primary 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 class="d-flex">
    <textarea id="inText" cols="40"></textarea>
    <button type="button" class="btn btn-primary" onclick="sendText()">Analyser !</button>
</div>
<div id="outText"></div>

{% endblock %}

{% block javascript %}
<script src="{% static 'scripts/home.js' %}"></script>
{% endblock %}

Recharger votre page, vous devriez voir le message "Le script est bien chargé!" dans la console javascript (F12, console), puis "L'utilisateur a cliqué sur le bouton !" quand vous cliquez sur le bouton "Analyser !". Si ce n'est pas le cas, vérifiez que le chemin vers le script est correct.

Envoyer une requête depuis le client vers le serveur

Bon très bien, maintenant, on veut envoyer le texte entré par l'utilisateur vers le serveur. Pour cela, la fonction sendText() doit récupérer le contenu de la textarea et l'envoyer dans une requête au serveur, puis récupérer le résultat et l'afficher. Dans ce genre de cas, on utilise une fonction asynchrone, qui permet d'exécuter une action et attendre la réponse avant d'en faire quelque chose.

 1 async function sendText() {
 2     // ON RÉCUPÈRE LES VARIABLES À ENVOYER AU SERVEUR
 3     var inText = document.getElementById('inText').value;
 4     
 5     // ON EMBALLE TOUT ÇA DANS UN JSON
 6     var colis = {
 7         inText: inText
 8     }
 9     console.log('Envoi colis:',colis);
10 
11     // PARAMÈTRES DE LA REQUÊTE
12     const requete = {
13         method: 'POST',
14         headers: {
15             'Content-Type': 'application/json'
16         },
17         body: JSON.stringify(colis)
18     };
19     
20     // ENVOI ET RÉCUPÉRATION DE LA RÉPONSE
21     const response = await fetch('/analyze/', requete)
22     const data = await response.json();
23     console.log(data);
24 }

Remarquez le async devant la définition de la fonction, et le await (lignes 21 et 22) qui permet d'attendre la réponse du serveur pour la mettre dans la variable data. C'est la même ligne 21 qui envoie la requête et qui récupère son résultat. La ligne 22 convertit la réponse en json pour pouvoir l'utiliser dans la suite du script. Pour l'instant, on se contente de l'afficher dans la console.

Vous avez aussi certainement remarqué que la requête est envoyée vers l'url '/analyze/' de notre appli. Il nous reste donc à faire une view pointée par cette url, et qui renverra une réponse.

Dans urls.py, importez le module suivant : from django.views.decorators.csrf import csrf_exempt, puis ajoutez cette nouvelle url qui appellera la fonction "analyze". Le csrf_exempt() est nécessaire pour accepter la requête entrante.

(...)
from resto import views as resto
from django.views.decorators.csrf import csrf_exempt

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', resto.home),
    path('variables/', resto.variables),
    path('analyze/', csrf_exempt(resto.analyze)),
]

Dans views.py, importez la librairie json pour interpréter la requête du client, importez aussi le module django JsonResponse qui nous permettra de renvoyer une réponse JSON, puis définissez votre view :

 1 from django.http import JsonResponse
 2 import json
 3 (...)
 4 def analyze(request):
 5     colis = json.loads(request.body)
 6     text = colis['inText']
 7     print("À analyser :",text)
 8 
 9     reponse = {
10         "reponse":"Merci !"
11     }
12     
13     return JsonResponse(reponse)

Dans cette view, on récupère le texte envoyé par l'utilisateur lignes 5 et 6, on le print un coup dans la console python pour vérifier qu'il est bien reçu, puis on prépare une réponse lignes 9-11, qu'on envoie ligne 13.

Vous devriez maintenant voir cette réponse s'afficher dans votre console javascript, côté client. Bravo !

Vous pouvez maintenant envoyer autant de variables que vous le souhaitez (en les mettant dans le "colis"), faire les traitements que vous voulez dans votre view, et renvoyer autant d'informations que vous voulez en réponse.

La même avec Spacy cette fois :)

Pour analyser le texte de l'utilisateur avec Spacy, il suffit de lancer l'analyse dans la view "analyze". On propose de renvoyer comme réponse une liste de tuples contenant chaque token (token.text) avec sa partie du discours (token.pos_) :

import json, spacy
(...)
def analyze(request):
    colis = json.loads(request.body)
    text = colis['inText']
    print("À analyser :",text)

    output = nlp(text)
    rep = []
    for token in output:
        rep.append((token.text, token.pos_))
    
    return JsonResponse({ "reponse":rep })

Dans home.js, on peut alors afficher le résultat dans la div outText qu'on avait préparée tout à l'heure :

    (...)
    // ENVOI ET RÉCUPÉRATION DE LA RÉPONSE
    const response = await fetch('/analyze/', requete)
    const data = await response.json();
    console.log(data);

    var outText = document.getElementById('outText');
    outText.innerHTML = ""; // vider la div si elle contenait déjà qqc
    for (token in data.reponse) {
        var tokenTuple = data.reponse[token];
        console.log(tokenTuple[0], tokenTuple[1]);
        outText.innerHTML += tokenTuple[0] + ' : ' + tokenTuple[1] + '<br/>';
    }
}

Voilà voilà. À partir de là, donnez libre cours à votre imagination !