Application Flask avec une base de données Notion 🚀

Introduction

Dans cet article, nous allons parcourir le processus de création d'une application web avec Flask, qui permet aux utilisateurs de saisir des informations via un formulaire et stocke ces données dans une base de données Notion. Nous couvrirons ensuite comment déployer gratuitement cette application sur Vercel !!

L'intégralité du code est disponible sur GitHub.

Prérequis

Pour suivre ce tutoriel, vous avez besoin des éléments suivants :

  • Connaissance de base en Python
  • Notions de base du développement web (HTML)
  • Compte Notion avec accès à l'API (si ça vous parle pas, pas de panique on va voir ça ensemble 🤗)

Étape 1️⃣ : Configuration de l'Environnement

Installez Flask, Flask-WTF, et Requests dans votre environnement Python :

pip install Flask Flask-WTF requests

Étape 2️⃣ : Création de l'Application Flask

Structure de l'Application

  • app.py : Le fichier principal de l'application Flask.
  • templates/ : Un dossier contenant les templates HTML pour le formulaire et l'affichage des données.

Définition du Formulaire

On commence par définir la structure de notre formulaire en créant une classe qui hérite de FlaskForm. Chaque champ du formulaire est représenté par un objet (par exemple, StringField pour du texte, SelectField pour une liste déroulante) avec des validateurs pour imposer certaines règles (comme DataRequired pour les champs obligatoires, Email pour valider les adresses email).

from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, SubmitField
from wtforms.validators import DataRequired, Email

class UserForm(FlaskForm):
    nom = StringField('Nom', validators=[DataRequired()])
    prenom = StringField('Prénom', validators=[DataRequired()])
    mail = StringField('Email', validators=[DataRequired(), Email()])
    humeur = SelectField('Humeur', choices=[("happy", "Happy"), ("sad", "Sad")], validators=[DataRequired()])
    submit = SubmitField('Envoyer')

Dans cet exemple, StringField et SelectField sont utilisés pour créer des champs de texte et une liste déroulante, respectivement. La liste des choix pour humeur est définie par un ensemble de tuples, où chaque tuple contient le code interne et l'affichage de l'option.

Intégration du formulaire dans une vue Flask

Après avoir défini la classe de formulaire, intégrez-la dans une vue Flask. Lorsque la route est sollicitée via GET, le formulaire est affiché à l'utilisateur. Si la méthode est POST et que le formulaire est validé, vous pouvez traiter les données.

@app.route('/', methods=['GET', 'POST'])
def home():
    form = UserForm()
    if form.validate_on_submit():
        # Traitement des données du formulaire
        nom = form.nom.data
        prenom = form.prenom.data
        mail = form.mail.data
        humeur = form.humeur.data
        # C'est ici qu'on va envoyer  les données à Notion
        # on voit ça un peu plus tard 🔥
        return redirect(url_for('home'))  # Redirection après le traitement
    return render_template('formulaire.html', form=form)

Rendu du formulaire dans un template HTML

Dans votre template HTML, utilisez les objets de formulaire passés depuis la vue pour générer le HTML du formulaire. Flask-WTF et WTForms facilitent cette tâche en offrant des méthodes pour rendre chaque champ ainsi que leurs labels et erreurs potentielles.

<form method="POST" action="">
  {{ form.hidden_tag() }}
  <p>{{ form.nom.label }} {{ form.nom() }}</p>
  <p>{{ form.prenom.label }} {{ form.prenom() }}</p>
  <p>{{ form.mail.label }} {{ form.mail() }}</p>
  <p>{{ form.humeur.label }} {{ form.humeur() }}</p>
  <p>{{ form.submit() }}</p>
</form>

{{ form.hidden_tag() }} est utilisé pour inclure un token CSRF, qui protège contre les attaques de type Cross-Site Request Forgery. Chaque champ est rendu avec son label ({{ form.nom.label }}) et le champ lui-même ({{ form.nom() }}).

On ajoute une route pour afficher les données

On ajoute simplement une route qui permet d'afficher les données stockées dans la base de données Notion.

@app.route('/database')
def voir_database():
    donnees = None
    # On récupère les données de la base de données Notion
    # On voit ça un peu plus tard 🔥
    return render_template('database.html', donnees=donnees)

Le template HTML associé est le suivant :

<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="UTF-8" />
    <title>Visualisation de la Base de Données</title>
  </head>
  <body>
    <h1>Données de la Base</h1>
    <table border="1">
      <thead>
        <tr>
          <th>Nom</th>
          <th>Prénom</th>
          <th>Email</th>
          <th>Humeur</th>
        </tr>
      </thead>
      <tbody>
        {% for item in donnees %}
        <tr>
          <td>{{ item['Nom'] }}</td>
          <td>{{ item['Prénom'] }}</td>
          <td>{{ item['Email'] }}</td>
          <td>{{ item['Humeur'] }}</td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
  </body>
</html>

Étape 3️⃣ : Utilisation de Notion comme Base de Données

Configuration de l'API Notion

Pour interagir avec l'API Notion et automatiser des tâches telles que la création de pages ou la récupération de données depuis une base de données Notion, vous aurez besoin d'un token d'intégration. Ce token agit comme une clé d'API, vous permettant d'authentifier vos requêtes à l'API Notion. Voici comment vous pouvez générer ce token.

Création d'une Intégration

  1. Accédez à votre compte Notion : Connectez-vous à votre compte Notion où vous souhaitez utiliser l'API.
  2. Ouvrez les paramètres d'intégration : Dans le coin inférieur gauche de l'interface Notion, cliquez sur votre avatar ou initiales, puis sélectionnez "Paramètres & Membres". Dans le menu latéral, choisissez l'onglet "Intégrations".
  3. Créez une nouvelle intégration : Cliquez sur le bouton "Nouvelle intégration". Remplissez le formulaire avec les détails de votre intégration :
    • Nom de l'intégration : Donnez un nom à votre intégration. Choisissez quelque chose de descriptif pour vous rappeler à quoi sert cette intégration.
    • Capacités d'intégration : Laissez les options par défaut ou ajustez-les selon vos besoins.
    • Associez à un espace de travail : Sélectionnez l'espace de travail Notion où vous souhaitez utiliser cette intégration.
  4. Soumettez le formulaire : Après avoir rempli les détails, cliquez sur "Soumettre" pour créer l'intégration.

Récupérer le token d'intégration

Une fois l'intégration créée, Notion affichera un token d'intégration (aussi appelé "Secret interne"). Copiez ce token et gardez-le en sécurité ; vous en aurez besoin pour authentifier vos requêtes à l'API Notion. Ce token est sensible et doit être traité comme un mot de passe.

Partager une base de données avec l'intégration

Pour que votre intégration puisse accéder à une base de données Notion spécifique, vous devez partager cette base de données avec l'intégration.

  1. Ouvrez la base de données dans Notion que vous souhaitez connecter à votre intégration.
  2. Cliquez sur "Partager" dans le coin supérieur droit de la page de la base de données.
  3. Ajoutez votre intégration : Dans le menu de partage, tapez le nom de l'intégration que vous avez créée et sélectionnez-la dans la liste. Cela donnera à l'intégration l'accès à la base de données.
  4. Ajustez les permissions si nécessaire : Assurez-vous que l'intégration a les permissions adéquates pour réaliser les actions que vous prévoyez (lire, écrire, etc.).

Stocker le token d'intégration et l'ID de la base de données

Pour utiliser le token d'intégration et l'ID de la base de données dans votre application Flask, vous pouvez les stocker dans des variables d'environnement. Cela vous permet de garder ces informations sensibles en sécurité et de les utiliser dans votre application sans les exposer directement dans votre code.

import os

NOTION_API_KEY = os.environ.get("NOTION_API_KEY")
DATABASE_ID = os.environ.get("DATABASE_ID")

Vous pouvez également utiliser un fichier .env pour stocker ces variables d'environnement. Pour cela, vous pouvez utiliser la bibliothèque python-dotenv pour charger ces variables dans votre application Flask.

from dotenv import load_dotenv

load_dotenv()

⚠️ Pensez à ajouter le fichier .env à votre fichier .gitignore pour éviter de le partager publiquement.

Utilisation de l'API Notion

Pour interagir avec l'API Notion, on va utiliser la bibliothèque requests pour envoyer des requêtes HTTP à l'API Notion. Pour un usage avancé vous êtes invité à lire la documentation officielle de l'API Notion.

Pour l'exemple que l'on traite ici nous avons besoin de deux fonctions.

  • La première pour créer une nouvelle page dans une base de données Notion correspondant aux données saisies par l'utilisateur.
  • La seconde pour récupérer les données de la base de données Notion et les afficher dans la page database.html.

La première fonction peut donc ressembler à ceci (pour bien comprendre la structure il faut vraiment aller voir la documentation de l'API Notion) :

def push_to_notion(nom, prenom, mail, humeur):
    url = "https://api.notion.com/v1/pages"
    token = os.environ.get("NOTION_API_KEY")
    database_id = os.environ.get("DATABASE_ID")

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
        "Notion-Version": "2022-06-28"
    }

    data = {
        "parent": {"database_id": database_id},
        "properties": {
            "Nom": {
                "title": [
                    {"text": {"content": nom}}
                ]
            },
            "Prénom": {
                "rich_text": [
                    {"text": {"content": prenom}}
                ]
            },
            "Email": {
                "email": mail
            },
            "Humeur": {
                "select": {"name": humeur}
            }
        }
    }

    response = requests.post(url, json=data, headers=headers)
    if response.status_code == 200:
        print("Data sent to Notion")
    else:
        print(f"Fail to sent data : {response.text}")

Pour visualiser les entrées existantes, c'est un peu plus simple. Il suffit d'envoyer une requête POST à l'endpoint /v1/databases/{database_id}/query de l'API Notion, en remplaçant {database_id} par l'ID de votre base de données. Cette requête ne nécessite pas de corps de requête pour récupérer toutes les entrées, mais peut être personnalisée pour filtrer les résultats si besoin.

def pull_from_notion():
    url = f"https://api.notion.com/v1/databases/{os.environ.get('DATABASE_ID')}/query"
    headers = {
        "Authorization": f"Bearer {os.environ.get('NOTION_API_KEY')}",
        "Notion-Version": "2022-06-28"
    }

    response = requests.post(url, headers=headers)
    if response.status_code == 200:
        entries = response.json()["results"]
        # Traitement des données, extraction et transformation selon les besoins
        return entries
    else:
        print(f"Erreur lors de la récupération des données : {response.text}")
        return []

Étape 4️⃣ : Déploiement de l'Application sur Vercel

Pour finir on va voir comment déployer gratuitement notre application en ligne. On va passer par le service de déploiement Vercel. Il en existe d'autre que vous pouvez utiliser comme Heroku par exemple. Tout d'abord il faut créer un compte sur Vercel.

Configuration de l'Environnement

Pour déployer votre application Flask sur Vercel, vous devez ajouter un fichier vercel.json à la racine de votre projet. Ce fichier contient des informations sur votre application, telles que les paramètres de déploiement, les variables d'environnement, etc.

{
  "version": 2,
  "builds": [
    {
      "src": "app.py",
      "use": "@vercel/python"
    }
  ],
  "routes": [{ "src": "/.*", "dest": "app.py" }]
}

Il faut également spécifier les dépendances de l'application dans un fichier requirements.txt à la racine de votre projet. Dans notre cas il s'agit de Flask, Flask-WTF, et requests.

Flask==2.0.1
Flask-WTF==0.15.1
requests==2.26.0

🔑 Pour spécifier à votre application les NOTION_API_KEY et DATABASE_ID il faut que vous passiez par le site de Vercel pour configurer des variables spécifiques à votre déploiement. Cela ne peut-être fait qu'une fois le projet connu de Vercel, ce que l'on voit juste en dessous.

Déploiement de l'Application

Pour déployer votre application sur Vercel, vous pouvez utiliser l'interface en ligne ou l'interface en ligne de commande. Pour l'interface en ligne, il suffit de suivre les étapes suivantes :

  1. Connectez-vous à votre compte Vercel.
  2. Cliquez sur "Nouveau Projet" pour importer votre application.
  3. Suivez les étapes pour importer votre application depuis un dépôt Git (GitHub, GitLab, Bitbucket, etc.).

Pour l'interface en ligne de commande, vous pouvez utiliser la commande vercel pour déployer votre application. Assurez-vous d'avoir installé le CLI Vercel sur votre machine.

vercel

Suivez les étapes pour déployer votre application. Vous pouvez également spécifier des variables d'environnement pour votre application lors du déploiement.

Conclusion

Et voilà, vous avez maintenant une application Flask qui stocke les données dans une base de données Notion et qui est déployée gratuitement sur Vercel ! Vous pouvez maintenant partager votre application avec le monde entier 🚀