One place for hosting & domains

      ajouter

      Comment ajouter une authentification à votre application avec Flask-Login


      Introduction

      Permettre aux utilisateurs de se connecter à votre application est l’une des fonctionnalités les plus courantes que vous ajouterez à votre application web. Cet article explique comment ajouter une authentification à votre application Flask avec le paquet Flask-Login.

      Gif animé de l'application Flask et boîte de connexion

      Nous allons créer des pages d’enregistrement et de connexion qui permettent aux utilisateurs de se connecter et d’accéder à des pages protégées que les utilisateurs qui ne sont pas connectés ne peuvent pas voir. Nous prendrons les informations du modèle utilisateur et les afficherons sur nos pages protégées lorsque l’utilisateur se connectera pour simuler à quoi ressemblerait un profil.

      Nous aborderons les points suivants dans cet article :

      • Utiliser la bibliothèque Flask-Login pour la gestion des sessions
      • Utiliser l’utilitaire Flask intégré pour le hachage des mots de passe
      • Ajouter des pages protégées à notre application pour les utilisateurs connectés uniquement
      • Utiliser Flask-SQLAlchemy pour créer un modèle d’utilisateur
      • Créer des formulaires d’enregistrement et de connexion pour que nos utilisateurs puissent créer des comptes et se connecter
      • Envoyer rapidement des messages d’erreur aux utilisateurs lorsque quelque chose ne va pas
      • Utiliser les informations du compte de l’utilisateur pour les afficher sur la page de profil

      Le code source de ce projet est disponible sur GitHub.

      Conditions préalables

      Pour terminer ce tutoriel, vous aurez besoin des éléments suivants :

      Notre application utilisera le modèle d’usine de l’application Flask avec des plans. Nous aurons un modèle qui gère tout ce qui est lié à la propriété auth, et nous en aurons un autre pour nos itinéraires réguliers, qui comprennent l’index et la page de profil protégé. Dans une véritable application, vous pouvez décomposer la fonctionnalité comme vous le souhaitez, mais la solution présentée ici fonctionnera bien pour ce tutoriel.

      Voici un diagramme qui vous donnera une idée de la structure des fichiers de votre projet une fois que vous aurez terminé le tutoriel :

      .
      └── flask_auth_app
          └── project
              ├── __init__.py       # setup our app
              ├── auth.py           # the auth routes for our app
              ├── db.sqlite         # our database
              ├── main.py           # the non-auth routes for our app
              ├── models.py         # our user model
              └── templates
                  ├── base.html     # contains common layout and links
                  ├── index.html    # show the home page
                  ├── login.html    # show the login form
                  ├── profile.html  # show the profile page
                  └── signup.html   # show the signup form
      

      Au fur et à mesure que nous avancerons dans le tutoriel, nous créerons ces répertoires et ces fichiers.

      Étape 1 — Installer des paquets

      Il y a trois paquets principaux dont nous avons besoin pour notre projet :

      • Flask
      • Flask-Login : pour gérer les sessions utilisateur après authentification
      • Flask-SQLAlchemy : pour représenter le modèle d’utilisateur et l’interface avec notre base de données

      Nous utiliserons SQLite pour éviter d’avoir à installer des dépendances supplémentaires pour la base de données.

      Tout d’abord, nous allons commencer par créer le répertoire des projets :

      Ensuite, nous devons naviguer vers le répertoire du projet :

      Vous voudrez créer un environnement Python si vous n’en avez pas. Selon la façon dont Python a été installé sur votre machine, vos commandes seront similaires :

      • python3 -m venv auth
      • source auth/bin/activate

      Note : vous pouvez consulter le tutoriel adapté à votre environnement local pour la mise en place de venv.

      Exécutez les commandes suivantes depuis votre environnement virtuel pour installer les paquets nécessaires :

      • pip install flask flask-sqlalchemy flask-login

      Maintenant que vous avez installé les paquets, vous êtes prêt à créer le fichier principal de l’application.

      Étape 2 — Création du dossier d’application principale

      Commençons par créer un répertoire project :

      Le premier dossier sur lequel nous travaillerons sera le fichier __init__.py pour notre projet :

      Ce fichier aura pour fonction de créer notre app, qui initialisera la base de données et enregistrera nos plans. Pour l’instant, cela ne fera pas grand-chose, mais ce sera nécessaire pour le reste de notre application. Nous devons initialiser SQLAlchemy, définir quelques valeurs de configuration et enregistrer nos plans ici.

      project/__init__.py

      from flask import Flask
      from flask_sqlalchemy import SQLAlchemy
      
      # init SQLAlchemy so we can use it later in our models
      db = SQLAlchemy()
      
      def create_app():
          app = Flask(__name__)
      
          app.config['SECRET_KEY'] = 'secret-key-goes-here'
          app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
      
          db.init_app(app)
      
          # blueprint for auth routes in our app
          from .auth import auth as auth_blueprint
          app.register_blueprint(auth_blueprint)
      
          # blueprint for non-auth parts of app
          from .main import main as main_blueprint
          app.register_blueprint(main_blueprint)
      
          return app
      

      Maintenant que nous avons le fichier principal de l’application, nous pouvons commencer à ajouter des itinéraires.

      Étape 3 — Ajouter des itinéraires

      Pour nos itinéraires, nous utiliserons deux plans. Pour notre plan principal, nous aurons une page d’accueil (/) et la page de profil (/profile) pour après s’être connecté. Si l’utilisateur tente d’accéder à la page de profil sans être connecté, il sera envoyé sur l’intinéraire de connexion.

      Pour notre plan d’authentification, nous aurons des itinéraires pour récupérer à la fois la page de connexion (/login) et la page d’inscription (/sign-up). Nous aurons également des itinéraires pour traiter les demandes POST provenant de ces deux itinéraires. Enfin, nous aurons un itinéraire de déconnexion (/logout) pour déconnecter un utilisateur actif.

      Pour l’instant, nous allons définir le login, signup, et logout avec des retours simples. Nous les réexaminerons à une étape ultérieure et les mettrons à jour avec la fonctionnalité souhaitée.

      Tout d’abord, créez main.py pour votre main_blueprint :

      project/main.py

      from flask import Blueprint
      from . import db
      
      main = Blueprint('main', __name__)
      
      @main.route('/')
      def index():
          return 'Index'
      
      @main.route('/profile')
      def profile():
          return 'Profile'
      

      Ensuite, créez auth.py pour votre auth_blueprint :

      project/auth.py

      from flask import Blueprint
      from . import db
      
      auth = Blueprint('auth', __name__)
      
      @auth.route('/login')
      def login():
          return 'Login'
      
      @auth.route('/signup')
      def signup():
          return 'Signup'
      
      @auth.route('/logout')
      def logout():
          return 'Logout'
      

      Dans un terminal, vous pouvez définir les valeurs FLASK_APP et FLASK_DEBUG :

      • export FLASK_APP=project
      • export FLASK_DEBUG=1

      La variable d’environnement FLASK_APP indique à Flask comment charger l’application. Elle doit indiquer où create_app est situé. Pour nos besoins, nous indiquerons le répertoire des projets.

      La variable d’environnement FLASK_DEBUG est activée en lui donnant la valeur 1, ce qui activera un débogueur qui affichera les erreurs de l’application dans le navigateur.

      Assurez-vous que vous êtes dans le répertoire flask_auth_app et puis exécutez le projet :

      Maintenant, dans un navigateur web, vous devriez être en mesure de naviguer vers les cinq URL possibles et voir le texte renvoyé qui a été défini dans auth.py et main.py.

      Par exemple, visiter localhost:5000/profile affiche : Profile :

      Capture d'écran du projet au port 5000 de localhost dans le navigateur

      Maintenant que nous avons vérifié que nos itinéraires se comportent comme prévu, nous pouvons passer à la création de modèles.

      Étape 4 — Créer des modèles

      Allons de l’avant et créons les modèles qui sont utilisés dans notre application. C’est la première étape avant que nous puissions mettre en œuvre la fonctionnalité de connexion proprement dite. Notre application utilisera quatre modèles :

      • index.html
      • profile.html
      • login.html
      • signup.html

      Nous aurons également un modèle de base qui aura un code commun à chacune des pages. Dans ce cas, le modèle de base sera doté de liens de navigation et de la disposition générale de la page. Créons-les maintenant.

      Tout d’abord, créez un répertoire de modèles sous le répertoire de project :

      • mkdir -p project/templates

      Ensuite, créez base.html :

      • nano project/templates/base.html

      Ensuite, ajoutez le code suivant au fichier base.html :

      project/templates/base.html

      <!DOCTYPE html>
      <html>
      
      <head>
          <meta charset="utf-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <title>Flask Auth Example</title>
          <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
      </head>
      
      <body>
          <section class="hero is-primary is-fullheight">
      
              <div class="hero-head">
                  <nav class="navbar">
                      <div class="container">
      
                          <div id="navbarMenuHeroA" class="navbar-menu">
                              <div class="navbar-end">
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("main.index') }}" class="navbar-item">
                                      Home
                                  </a>
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("main.profile') }}" class="navbar-item">
                                      Profile
                                  </a>
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.login') }}" class="navbar-item">
                                      Login
                                  </a>
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.signup') }}" class="navbar-item">
                                      Sign Up
                                  </a>
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.logout') }}" class="navbar-item">
                                      Logout
                                  </a>
                              </div>
                          </div>
                      </div>
                  </nav>
              </div>
      
              <div class="hero-body">
                  <div class="container has-text-centered">
                     {% block content %}
                     {% endblock %}
                  </div>
              </div>
          </section>
      </body>
      
      </html>
      

      Ce code créera une série de liens de menu vers chaque page de l’application et une zone où le contenu apparaîtra .

      Remarque : En arrière-plan, nous utilisons Bulma pour s’occuper du style et de la mise en page. Pour une plongée plus approfondie dans Bulma, pensez à lire la documentation officielle de Bulma.

      Ensuite, créez templates/index.html:

      • nano project/templates/index.html

      Ajoutez le code suivant au fichier nouvellement créé pour ajouter du contenu à la page :

      project/templates/index.html

      {% extends "base.html" %}
      
      {% block content %}
      <h1 class="title">
        Flask Login Example
      </h1>
      <h2 class="subtitle">
        Easy authentication and authorization in Flask.
      </h2>
      {% endblock %}
      

      Ce code permettra de créer une page d’index de base avec un titre et un sous-titre.

      Ensuite, créez templates/login.html :

      • nano project/templates/login.html

      Ce code génère une page de connexion avec des champs pour Email et Password. Il y a également une case à cocher pour « se souvenir » d’une session connectée.

      project/templates/login.html

      {% extends "base.html" %}
      
      {% block content %}
      <div class="column is-4 is-offset-4">
          <h3 class="title">Login</h3>
          <div class="box">
              <form method="POST" action="/login">
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="email" name="email" placeholder="Your Email" autofocus="">
                      </div>
                  </div>
      
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="password" name="password" placeholder="Your Password">
                      </div>
                  </div>
                  <div class="field">
                      <label class="checkbox">
                          <input type="checkbox">
                          Remember me
                      </label>
                  </div>
                  <button class="button is-block is-info is-large is-fullwidth">Login</button>
              </form>
          </div>
      </div>
      {% endblock %}
      

      Ensuite, créez templates/signup.html :

      • nano project/templates/signup.html

      Ajoutez le code suivant pour créer une page d’inscription avec des champs pour email, name, et password :

      project/templates/signup.html

      {% extends "base.html" %}
      
      {% block content %}
      <div class="column is-4 is-offset-4">
          <h3 class="title">Sign Up</h3>
          <div class="box">
              <form method="POST" action="/signup">
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="email" name="email" placeholder="Email" autofocus="">
                      </div>
                  </div>
      
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="text" name="name" placeholder="Name" autofocus="">
                      </div>
                  </div>
      
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="password" name="password" placeholder="Password">
                      </div>
                  </div>
      
                  <button class="button is-block is-info is-large is-fullwidth">Sign Up</button>
              </form>
          </div>
      </div>
      {% endblock %}
      

      Ensuite, créez templates/profile.html :

      • nano project/templates/profile.html

      Ajoutez ce code pour créer une page simple avec un titre codé en dur pour accueillir Anthony:

      project/templates/profile.html

      {% extends "base.html" %}
      
      {% block content %}
      <h1 class="title">
        Welcome, Anthony!
      </h1>
      {% endblock %}
      

      Plus tard, nous ajouterons du code pour saluer dynamiquement tout utilisateur.

      Une fois que vous avez ajouté les modèles, nous pouvons mettre à jour les déclarations de retour dans chacun des itinéraires ; nous devons renvoyer les modèles au lieu du texte.

      Ensuite, mettez à jour main.py en modifiant la ligne d’importation et les itinéraires pour index et profile :

      project/main.py

      from flask import Blueprint, render_template
      ...
      @main.route('/')
      def index():
          return render_template('index.html')
      
      @main.route('/profile')
      def profile():
          return render_template('profile.html')
      

      Vous allez maintenant mettre à jour auth.py en modifiant la ligne d’importation et les itinéraires pour login et signup :

      project/auth.py

      from flask import Blueprint, render_template
      ...
      @auth.route('/login')
      def login():
          return render_template('login.html')
      
      @auth.route('/signup')
      def signup():
          return render_template('signup.html')
      

      Une fois que vous avez effectué ces changements, voici à quoi ressemble la page d’inscription si vous naviguez vers /signup :

      Page d'inscription à /signup

      Vous devriez pouvoir voir également les pages pour /, /login et /profile.

      Nous laisserons /logout seul pour l’instant car il n’affichera pas de modèle quand il sera terminé.

      Étape 5 — Créer des modèles d’utilisateurs

      Notre modèle d’utilisateur représente ce que cela signifie pour notre app d’avoir un utilisateur. Nous aurons des champs pour une adresse électronique, un mot de passe et un nom. Dans votre application, vous pouvez décider que vous souhaitez que beaucoup plus d’informations soient stockées par utilisateur. Vous pouvez ajouter des éléments tels que l’anniversaire, la photo de profil, la localisation ou toute autre préférence de l’utilisateur.

      Les modèles créés dans Flask-SQLAlchemy sont représentés par des classes qui sont ensuite traduites en tables dans une base de données. Les attributs de ces classes se transforment alors en colonnes pour ces tables.

      Allons de l’avant et créons ce modèle d’utilisateur :

      Ce code crée un modèle d’utilisateur avec des colonnes pour un id, email, password et un name :

      project/models.py

      from . import db
      
      class User(db.Model):
          id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy
          email = db.Column(db.String(100), unique=True)
          password = db.Column(db.String(100))
          name = db.Column(db.String(1000))
      

      Maintenant que vous avez créé un modèle d’utilisateur, vous pouvez passer à la configuration de votre base de données.

      Étape 6 — Configurer la base de données

      Comme indiqué dans les conditions préalables, nous utiliserons une base de données SQLite. Nous pourrions créer nous-mêmes une base de données SQLite, mais laissons Flask-SQLAlchemy le faire pour nous. Nous avons déjà le chemin de la base de données spécifié dans le fichier__init__.py,il suffit donc de dire à Flask-SQLAlchemy de créer la base de données dans le REPL Python.

      Si vous arrêtez votre application et ouvrez un REPL en Python, nous pouvons créer la base de données en utilisant la méthode create_all sur l’objet db. Assurez-vous que vous êtes toujours dans l’environnement virtuel et dans le répertoire flask_auth_app.

      • from project import db, create_app
      • db.create_all(app=create_app()) # pass the create_app result so Flask-SQLAlchemy gets the configuration.

      Note : Si l’utilisation de l’interpréteur Python est nouvelle pour vous, vous pouvez consulter la documentation officielle.

      Vous allez maintenant voir un fichier db.sqlite dans le répertoire de votre projet. Cette base de données contiendra notre table d’utilisateurs.

      Étape 7 — Mettre en place la fonction d’autorisation

      Pour notre fonction d’inscription, nous allons prendre les données que l’utilisateur tape dans le formulaire et les ajouter à notre base de données. Avant de les ajouter, nous devons nous assurer que l’utilisateur n’existe pas déjà dans la base de données. Si ce n’est pas le cas, nous devons nous assurer que nous avons bien haché le mot de passe avant de le placer dans la base de données, car nous ne voulons pas que nos mots de passe soient stockés en clair.

      Commençons par ajouter une deuxième fonction pour traiter les données du formulaire POST. Dans cette fonction, nous allons d’abord recueillir les données transmises par l’utilisateur.

      Créez la fonction et ajoutez une redirection vers le bas. Cela permettra à l’utilisateur de faire l’expérience d’une inscription réussie et d’être dirigé vers la page de connexion.

      Mettez à jour auth.py en modifiant la ligne d’importation et en mettant en œuvre signup_post :

      project/auth.py

      from flask import Blueprint, render_template, redirect, url_for
      ...
      @auth.route('/signup', methods=['POST'])
      def signup_post():
          # code to validate and add user to database goes here
          return redirect(url_for('auth.login'))
      

      Maintenant, ajoutons le reste du code nécessaire à l’inscription d’un utilisateur.

      Pour commencer, nous devrons utiliser l’objet de demande pour obtenir les données du formulaire.

      Continuez à mettre à jour auth.py en ajoutant des importations et en mettant en œuvre signup_post:

      auth.py

      from flask import Blueprint, render_template, redirect, url_for, request
      from werkzeug.security import generate_password_hash, check_password_hash
      from .models import User
      from . import db
      ...
      @auth.route('/signup', methods=['POST'])
      def signup_post():
          email = request.form.get('email')
          name = request.form.get('name')
          password = request.form.get('password')
      
          user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database
      
          if user: # if a user is found, we want to redirect back to signup page so user can try again
              return redirect(url_for('auth.signup'))
      
          # create a new user with the form data. Hash the password so the plaintext version isn't saved.
          new_user = User(email=email, name=name, password=generate_password_hash(password, method='sha256'))
      
          # add the new user to the database
          db.session.add(new_user)
          db.session.commit()
      
          return redirect(url_for('auth.login'))
      

      Remarque : Le stockage des mots de passe en clair est considéré comme une mauvaise pratique de sécurité. Vous voudrez généralement utiliser un algorithme de hachage complexe et un sel de mot de passe pour assurer la sécurité des mots de passe.

      Étape 8 — Tester la méthode d’inscription

      Maintenant que la méthode d’inscription est terminée, nous devrions être en mesure de créer un nouvel utilisateur. Utilisez le formulaire pour créer un utilisateur.

      Il y a deux façons de vérifier si l’inscription a fonctionné : vous pouvez utiliser un visualiseur de base de données pour regarder la ligne qui a été ajoutée à votre table, ou vous pouvez essayer de vous inscrire à nouveau avec la même adresse électronique, et si vous obtenez une erreur, vous savez que le premier courriel a été enregistré correctement. Adoptons donc cette approche.

      Nous pouvons ajouter un code pour faire savoir à l’utilisateur que le courriel existe déjà et lui dire de se rendre à la page de connexion. En appelant la fonction flash, nous enverrons un message à la demande suivante, qui dans ce cas, est la redirection. La page sur laquelle nous arrivons aura alors accès à ce message dans le modèle.

      D’abord, nous ajoutons le flash avant de rediriger vers notre page d’enregistrement.

      project/auth.py

      from flask import Blueprint, render_template, redirect, url_for, request, flash
      ...
      @auth.route('/signup', methods=['POST'])
      def signup_post():
          ...
          if user: # if a user is found, we want to redirect back to signup page so user can try again
              flash('Email address already exists')
              return redirect(url_for('auth.signup'))
      

      Pour obtenir le message clignotant dans le modèle, nous pouvons ajouter ce code au-dessus du formulaire. Le message s’affichera alors directement au-dessus du formulaire.

      project/templates/signup.html

      ...
      {% with messages = get_flashed_messages() %}
      {% if messages %}
          <div class="notification is-danger">
              {{ messages[0] }}. Go to <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.login') }}">login page</a>.
          </div>
      {% endif %}
      {% endwith %}
      <form method="POST" action="/signup">
      

      Boîte d'inscription affichant un message qui indique que l'adresse électronique existe déjà. Allez à la page de login dans une boîte rose foncé

      Étape 9 — Ajouter la méthode de connexion

      La méthode de connexion est similaire à la fonction d’inscription en ce sens que nous prenons les informations de l’utilisateur et en faisons quelque chose. Dans ce cas, nous comparerons l’adresse électronique saisie pour voir si elle se trouve dans la base de données. Si c’est le cas, nous testerons le mot de passe fourni par l’utilisateur en hachant le mot de passe que l’utilisateur nous a communiqué et en le comparant au mot de passe haché dans la base de données. Nous savons que l’utilisateur a saisi le bon mot de passe lorsque les deux mots de passe hachés correspondent.

      Une fois que l’utilisateur a passé le contrôle du mot de passe, nous savons qu’il possède les bonnes références et nous pouvons le connecter en utilisant Flask-Login. En appelant login_user, Flask-Login créera une session pour cet utilisateur qui persistera tant que l’utilisateur restera connecté, ce qui lui permettra de voir les pages protégées.

      Nous pouvons commencer par un nouveau mode de traitement des données POSTed. Nous redirigerons vers la page de profil lorsque l’utilisateur se connectera avec succès :

      project/auth.py

      ...
      @auth.route('/login', methods=['POST'])
      def login_post():
          # login code goes here
          return redirect(url_for('main.profile'))
      

      Maintenant, nous devons vérifier si l’utilisateur possède les bons identifiants

      project/auth.py

      ...
      @auth.route('/login', methods=['POST'])
      def login_post():
          email = request.form.get('email')
          password = request.form.get('password')
          remember = True if request.form.get('remember') else False
      
          user = User.query.filter_by(email=email).first()
      
          # check if the user actually exists
          # take the user-supplied password, hash it, and compare it to the hashed password in the database
          if not user or not check_password_hash(user.password, password):
              flash('Please check your login details and try again.')
              return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page
      
          # if the above check passes, then we know the user has the right credentials
          return redirect(url_for('main.profile'))
      

      Ajoutons le bloc dans le modèle pour que l’utilisateur puisse voir le message clignotant. Comme pour le formulaire d’inscription, ajoutons le message d’erreur potentiel directement au-dessus du formulaire :

      project/templates/login.html

      ...
      {% with messages = get_flashed_messages() %}
      {% if messages %}
          <div class="notification is-danger">
              {{ messages[0] }}
          </div>
      {% endif %}
      {% endwith %}
      <form method="POST" action="/login">
      

      Nous avons maintenant la possibilité de dire qu’un utilisateur a été connecté avec succès, mais il n’y a rien pour connecter l’utilisateur. C’est là que nous introduisons Flask-Login pour gérer les sessions des utilisateurs.

      Avant de commencer, nous avons besoin de quelques éléments pour que Flask-Login fonctionne. Commencez par ajouter le UserMixin à votre modèle User. Le UserMixin ajoutera les attributs de Flask-Login au modèle afin que Flask-Login puisse travailler avec lui.

      models.py

      from flask_login import UserMixin
      from . import db
      
      class User(UserMixin, db.Model):
          id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy
          email = db.Column(db.String(100), unique=True)
          password = db.Column(db.String(100))
          name = db.Column(db.String(1000))
      

      Ensuite, nous devons spécifier notre chargeur d’utilisateurs. Un chargeur d’utilisateur indique à Flask-Login comment trouver un utilisateur spécifique à partir de son identifiant stocké dans son cookie de session. Nous pouvons l’ajouter dans notre create_app ainsi que le code init du Flask-Login :

      project/__init__.py

      ...
      from flask_login import LoginManager
      ...
      def create_app():
          ...
          db.init_app(app)
      
          login_manager = LoginManager()
          login_manager.login_view = 'auth.login'
          login_manager.init_app(app)
      
          from .models import User
      
          @login_manager.user_loader
          def load_user(user_id):
              # since the user_id is just the primary key of our user table, use it in the query for the user
              return User.query.get(int(user_id))
      

      Enfin, nous pouvons ajouter le login_user juste avant de rediriger vers la page de profil pour créer la session :

      project/auth.py

      from flask_login import login_user
      from .models import User
      ...
      @auth.route('/login', methods=['POST'])
      def login_post():
          ...
          # if the above check passes, then we know the user has the right credentials
          login_user(user, remember=remember)
          return redirect(url_for('main.profile'))
      

      Avec la configuration de Flask-Login, nous pouvons utiliser l’itinéraire /login. Lorsque tout est en place, vous verrez la page de profil.

      Page de profil avec « Welcome, Anthony! »

      Étape 10 — Protéger les pages

      Si votre nom n’est pas aussi Anthony, alors vous verrez que votre nom est faux. Ce que nous voulons, c’est que le profil affiche le nom dans la base de données. Nous devons donc d’abord protéger la page et ensuite accéder aux données de l’utilisateur pour obtenir le nom.

      Pour protéger une page lors de l’utilisation de Flask-Login, nous ajoutons le décorateur @login_required entre l’itinéraire et la fonction. Cela empêchera un utilisateur qui n’est pas connecté de voir l’itinéraire. Si l’utilisateur n’est pas connecté, il sera redirigé vers la page de connexion, selon la configuration du Flask-Login.

      Avec les itinéraires qui sont décorés avec le décorateur @login_required, nous avons alors la possibilité d’utiliser l’objet current_user à l’intérieur de la fonction. Ce current_user représente l’utilisateur de la base de données, et nous pouvons accéder à tous les attributs de cet utilisateur avec la notation par points. Par exemple, current_user.email, current_user.password, et current_user.name, et current_user.id renverront les valeurs réelles stockées dans la base de données pour l’utilisateur connecté.

      Utilisons le nom de l’utilisateur actuel et envoyons-le au modèle. Nous utiliserons alors ce nom et afficherons sa valeur.

      project/main.py

      from flask_login import login_required, current_user
      ...
      @main.route('/profile')
      @login_required
      def profile():
          return render_template('profile.html', name=current_user.name)
      

      Ensuite, dans le fichier profile.html, mettez à jour la page pour afficher la valeur name :

      project/templates/profile.html

      ...
      <h1 class="title">
        Welcome, {{ name }}!
      </h1>
      

      Une fois que nous nous rendons sur notre page de profil, nous voyons alors que le nom de l’utilisateur apparaît.

      Page d'accueil de l'utilisateur avec le nom de l'utilisateur actuellement connecté

      La dernière chose que nous pouvons faire est de mettre à jour la vue de déconnexion. Nous pouvons appeler le logout_user dans un itinéraire de déconnexion. Nous avons le décorateur @login_required parce qu’il n’est pas logique de déconnecter un utilisateur qui n’est pas connecté au départ.

      project/auth.py

      from flask_login import login_user, logout_user, login_required
      ...
      @auth.route('/logout')
      @login_required
      def logout():
          logout_user()
          return redirect(url_for('main.index'))
      

      Lorsque nous nous déconnectons et que nous essayons de consulter à nouveau la page de profil, nous voyons apparaître un message d’erreur. C’est parce que Flask-Login fait clignoter un message pour nous lorsque l’utilisateur n’est pas autorisé à accéder à une page.

      Page de connexion avec un message indiquant que l'utilisateur doit se connecter pour accéder à la page

      Une dernière chose que nous pouvons faire est de mettre des déclarations if dans les modèles pour afficher uniquement les liens pertinents pour l’utilisateur. Ainsi, avant que l’utilisateur ne se connecte, il aura la possibilité de se connecter ou de s’inscrire. Une fois que l’on se connecte, on peut aller sur son profil ou se déconnecter :

      templates/base.html

      ...
      <div class="navbar-end">
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("main.index') }}" class="navbar-item">
              Home
          </a>
          {% if current_user.is_authenticated %}
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("main.profile') }}" class="navbar-item">
              Profile
          </a>
          {% endif %}
          {% if not current_user.is_authenticated %}
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.login') }}" class="navbar-item">
              Login
          </a>
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.signup') }}" class="navbar-item">
              Sign Up
          </a>
          {% endif %}
          {% if current_user.is_authenticated %}
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.logout') }}" class="navbar-item">
              Logout
          </a>
          {% endif %}
      </div>
      

      Page d'accueil avec la navigation « Home, Login, and Sign Up» en haut de l'écran

      Grâce à cela, vous avez réussi à construire votre application avec authentification.

      Conclusion

      Nous avons utilisé Flask-Login et Flask-SQLAlchemy afin de créer un système de connexion pour notre app. Nous avons abordé la manière d’authentifier un utilisateur en créant d’abord un modèle d’utilisateur et en stockant les informations sur l’utilisateur. Ensuite, nous avons dû vérifier que le mot de passe de l’utilisateur était correct en hachant le mot de passe du formulaire et en le comparant à celui stocké dans la base de données. Enfin, nous avons ajouté l’autorisation à notre app en utilisant le décorateur @login_required sur une page de profil afin que seuls les utilisateurs connectés puissent voir cette page.

      Ce que nous avons créé dans ce tutoriel sera suffisant pour les petites applications, mais si vous souhaitez avoir plus de fonctionnalités dès le début, vous pouvez envisager d’utiliser les bibliothèques Flask-User ou Flask-Security qui sont toutes deux construites sur la bibliothèque Flask-Login.



      Source link

      Comment ajouter Swap sur Ubuntu 20.04


      Introduction

      Une façon de se prémunir contre les erreurs de mémoire dans les applications est d’ajouter un espace swap à votre serveur. Dans ce guide, nous verrons comment ajouter un fichier swap à un serveur Ubuntu 20.04.

      Warning : Bien que le swap soit généralement recommandé pour les systèmes utilisant des disques durs tournants traditionnels, le fait de placer le swap sur des SSD peut entraîner des problèmes de dégradation du matériel au fil du temps.   Pour cette raison, nous ne recommandons pas de permettre le swap sur DigitalOcean ou tout autre fournisseur qui utilise le stockage SSD.

      Qu’est-ce que le swap?

      Le swap est une partie du stockage du disque dur qui a été mise de côté pour que le système d’exploitation puisse stocker temporairement les données qu’il ne peut plus conserver en mémoire vive.   Cela vous permet d’augmenter la quantité d’informations que votre serveur peut conserver dans sa mémoire de travail, avec quelques réserves. L’espace swap sur le disque dur sera utilisé principalement lorsque l’espace en mémoire vive ne sera plus suffisant pour contenir les données des applications en cours d’utilisation.

      Les informations écrites sur le disque seront nettement plus lentes que celles conservées dans la mémoire vive, mais le système d’exploitation préférera conserver les données des applications en mémoire et utiliser le swap pour les données plus anciennes. Dans l’ensemble, le fait de disposer d’un espace swap comme solution de repli lorsque la mémoire vive de votre système est épuisée peut constituer un bon filet de sécurité contre les exceptions de sortie de mémoire sur les systèmes disposant d’un stockage non-SSD.

      Étape 1 – Vérification du système d’information sur les swaps

      Avant de commencer, nous pouvons vérifier si le système dispose déjà d’un espace swap disponible. Il est possible d’avoir plusieurs fichiers swap ou partitions swap, mais en général, un seul devrait suffire.

      Nous pouvons voir si le système dispose d’un échange configuré en tapant :

      Si vous ne récupérez pas les résultats, cela signifie que votre système ne dispose pas actuellement d’espace swap disponible.

      Vous pouvez vérifier qu’il n’y a pas de swap actif en utilisant l’utilitaire free :

      Output

      total used free shared buff/cache available Mem: 981Mi 122Mi 647Mi 0.0Ki 211Mi 714Mi Swap: 0B 0B 0B

      Comme vous pouvez le voir dans la ligne Swap du résultat, aucun swap n’est actif sur le système.

      Étape 2 – Vérifier de l’espace disponible sur la partition du disque dur

      Avant de créer notre fichier swap, nous vérifierons notre utilisation actuelle du disque pour nous assurer que nous avons suffisamment d’espace. Faites ceci en entrant :

      Output

      Filesystem Size Used Avail Use% Mounted on udev 474M 0 474M 0% /dev tmpfs 99M 932K 98M 1% /run /dev/vda1 25G 1.4G 23G 7% / tmpfs 491M 0 491M 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 491M 0 491M 0% /sys/fs/cgroup /dev/vda15 105M 3.9M 101M 4% /boot/efi /dev/loop0 55M 55M 0 100% /snap/core18/1705 /dev/loop1 69M 69M 0 100% /snap/lxd/14804 /dev/loop2 28M 28M 0 100% /snap/snapd/7264 tmpfs 99M 0 99M 0% /run/user/1000

      L’appareil avec / dans la colonne Mounted on est ici notre disque. Nous avons beaucoup d’espace disponible dans cet exemple (seulement 1,4 G utilisé). Votre usage sera probablement différent.

      Bien qu’il existe de nombreuses opinions sur la taille appropriée d’un espace swap, cela dépend vraiment de vos préférences personnelles et des exigences de votre demande. En général, une quantité égale ou double de la quantité de mémoire vive de votre système est un bon point de départ. Une autre bonne règle de base est que tout ce qui dépasse 4G de swap est probablement inutile si vous l’utilisez simplement comme solution de repli de la RAM.

      Étape 3 – Créer d’un fichier swap

      Maintenant que nous connaissons l’espace disponible sur notre disque dur, nous pouvons créer un fichier swap sur notre système de fichiers. Nous allons attribuer un fichier de la taille que nous voulons appelé swapfile dans notre répertoire root (/).

      Le meilleur moyen de créer un fichier swap est le programme fallocate. Cette commande crée instantanément un fichier de la taille spécifiée.

      Comme le serveur de notre exemple a 1G de mémoire vive, nous allons créer un fichier de 1G dans ce guide. Ajustez cela pour répondre aux besoins de votre propre serveur :

      • sudo fallocate -l 1G /swapfile

      Nous pouvons vérifier que la quantité d’espace correcte a été réservée en tapant :

      • -rw-r--r-- 1 root root 1.0G Apr 25 11:14 /swapfile

      Notre dossier a été créé avec la bonne quantité d’espace réservé.

      Étape 4 – Activer le fichier Swap

      Maintenant que nous disposons d’un fichier de la bonne taille, nous devons le transformer en espace swap.

      Tout d’abord, nous devons verrouiller les permissions du fichier afin que seuls les utilisateurs ayant les privilèges root puissent en lire le contenu. Cela empêche les utilisateurs normaux de pouvoir accéder au fichier, ce qui aurait des implications importantes en matière de sécurité.

      Rendre le fichier accessible uniquement au root en tapant : 

      Vérifiez la modification des autorisations en tapant :

      Output

      -rw------- 1 root root 1.0G Apr 25 11:14 /swapfile

      Comme vous pouvez le voir, seul le root user a les drapeaux de lecture et d’écriture activés.

      Nous pouvons maintenant marquer le fichier comme espace swap en tapant :

      Output

      Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes) no label, UUID=6e965805-2ab9-450f-aed6-577e74089dbf

      Après avoir marqué le fichier, nous pouvons activer le fichier swap, ce qui permet à notre système de commencer à l’utiliser :

      Vérifiez que le swap est disponible en tapant :

      Output

      NAME TYPE SIZE USED PRIO /swapfile file 1024M 0B -2

      Nous pouvons vérifier à nouveau les résultats de l’utilitaire free pour corroborer nos conclusions :

      Output

      total used free shared buff/cache available Mem: 981Mi 123Mi 644Mi 0.0Ki 213Mi 714Mi Swap: 1.0Gi 0B 1.0Gi

      Notre swap a été mis en place avec succès et notre système d’exploitation commencera à l’utiliser si nécessaire.

      Étape 5 – Rendre le fichier swap permanent

      Nos récents changements ont permis d’activer le fichier swap pour la session en cours. Cependant, si nous redémarrons, le serveur ne conservera pas automatiquement les paramètres du swap. Nous pouvons changer cela en ajoutant le fichier swap à notre fichier /etc/fstab.

      Sauvegardez le fichier /etc/fstab au cas où quelque chose n’irait pas :

      • sudo cp /etc/fstab /etc/fstab.bak

      Ajoutez les informations du fichier swap à la fin de votre fichier /etc/fstab en tapant : 

      • echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

      Ensuite, nous allons revoir certains paramètres que nous pouvons mettre à jour pour régler notre espace swap.

      Étape 6 – Réglage de vos paramètres swap

      Il existe quelques options que vous pouvez configurer et qui auront un impact sur les performances de votre système lors de la gestion des swaps.

      Ajuster la propriété du swappiness

      Le paramètre swappiness permet de configurer la fréquence à laquelle votre système échange des données de la mémoire vive vers l’espace swap. Il s’agit d’une valeur comprise entre 0 et 100 qui représente un pourcentage.

      Avec des valeurs proches de zéro, le noyau n’échangera pas de données sur le disque à moins que cela ne soit absolument nécessaire. N’oubliez pas que les interactions avec le fichier swap sont « lourdes » dans la mesure où elles prennent beaucoup plus de temps que les interactions avec la mémoire vive et qu’elles peuvent entraîner une réduction significative des performances. Le fait de dire au système de ne pas trop dépendre du swap rendra généralement votre système plus rapide.

      Les valeurs plus proches de 100 tenteront de mettre plus de données dans le swap afin de garder plus d’espace RAM libre. En fonction du profil de mémoire de vos applications ou de l’utilisation que vous faites de votre serveur, cela peut être préférable dans certains cas.

      On peut voir la valeur actuelle du swap en tapant :

      • cat /proc/sys/vm/swappiness

      Output

      60

      Pour un ordinateur de bureau, un paramètre de swappiness de 60 n’est pas une mauvaise valeur. Pour un serveur, vous voudrez peut-être le rapprocher de 0.

      Nous pouvons régler le swappiness à une valeur différente en utilisant la commande sysctl.

      Par exemple, pour régler le swappiness sur 10, nous pourrions taper :

      • sudo sysctl vm.swappiness=10

      Output

      vm.swappiness = 10

      Ce réglage persistera jusqu’au prochain redémarrage. Nous pouvons fixer cette valeur automatiquement au redémarrage en ajoutant la ligne à notrefichier /etc/sysctl.conf : 

      • sudo nano /etc/sysctl.conf

      En bas, vous pouvez ajouter :

      /etc/sysctl.conf

      vm.swappiness=10
      

      Enregistrez et fermez le fichier lorsque vous avez terminé.

      Ajuster le réglage de la pression du cache

      Une autre valeur connexe que vous pourriez vouloir modifier est la vfs_cache_pressure.   Ce paramètre configure la quantité que le système choisira pour mettre en cache les informations d’inode et de dentry sur d’autres données.

      Fondamentalement, il s’agit de données d’accès au système de fichiers. Il est généralement très difficile à consulter et très souvent demandé, c’est donc une excellente chose pour votre système de mettre en cache. Vous pouvez voir la valeur actuelle en interrogeant à nouveau le système de fichiers proc :

      • cat /proc/sys/vm/vfs_cache_pressure

      Output

      100

      Dans sa configuration actuelle, notre système supprime trop rapidement les informations d’inode du cache. Nous pouvons fixer ce chiffre à un niveau plus conservateur, comme 50, en tapant :

      • sudo sysctl vm.vfs_cache_pressure=50

      Output

      vm.vfs_cache_pressure = 50

      Encore une fois, ceci n’est valable que pour notre session actuelle. Nous pouvons changer cela en l’ajoutant à notre fichier de configuration comme nous l’avons fait avec notre réglage du swappiness :

      • sudo nano /etc/sysctl.conf

      En bas, ajoutez la ligne qui spécifie votre nouvelle valeur :

      /etc/sysctl.conf

      vm.vfs_cache_pressure=50
      

      Enregistrez et fermez le fichier lorsque vous avez terminé.

      Conclusion

      En suivant les étapes décrites dans ce guide, vous aurez une certaine marge de manœuvre dans les cas qui, autrement, entraîneraient des exceptions hors mémoire. L’espace de swap peut être incroyablement utile pour éviter certains de ces problèmes courants.

      Si vous rencontrez des erreurs OOM (out of memory), ou si vous constatez que votre système est incapable d’utiliser les applications dont vous avez besoin, la meilleure solution est d’optimiser vos configurations d’applications ou de mettre à niveau votre serveur.



      Source link

      Comment ajouter les tests unitaires à votre projet Django


      L’auteur a choisi le Open Internet/Free Speech Fund pour recevoir un don dans le cadre du programme Write for Donations.

      Introduction

      Il est presque impossible de construire des sites web qui fonctionnent parfaitement du premier coup sans erreurs. C’est pourquoi vous devez tester votre application web pour trouver ces erreurs et y remédier de manière proactive. Afin d’améliorer l’efficacité des tests, il est courant de décomposer les tests en unités qui testent des fonctionnalités spécifiques de l’application web. Cette pratique est appelée les tests unitaires.   Il est plus facile de détecter les erreurs, car les tests se concentrent sur de petites parties (unités) de votre projet indépendamment des autres parties.

      Tester un site web peut être une tâche complexe à entreprendre car il est constitué de plusieurs couches de logique comme le traitement des requêtes HTTP, la validation des formulaires et les modèles de rendu. Cependant, Django fournit un ensemble d’outils qui permettent de tester votre application web en toute transparence.   Dans Django, la façon préférée d’écrire des tests est d’utiliser le module Python unittest, bien qu’il soit possible d’utiliser d’autres cadres de test. 

      Dans ce tutoriel, vous allez mettre en place une suite de tests dans votre projet Django et écrire des tests unitaires pour les modèles et les vues de votre application. Vous effectuerez ces tests, analyserez leurs résultats et apprendrez comment trouver les causes des échecs.

      Conditions préalables

      Avant de commencer ce tutoriel, vous aurez besoin des éléments suivants :

      Étape 1 – Ajouter une séquence de tests à votre demande Django

      Une séquence de tests dans Django est une collection de tous les scénarios de test de toutes les applications de votre projet. Pour permettre à l’utilitaire de test de Django de découvrir les scénarios de test que vous avez, vous écrivez les scénarios de test dans des scripts dont le nom commence par test.   Au cours de cette étape, vous allez créer la structure des répertoires et des fichiers de votre séquence de tests, et y créer un scénario de test vide.

      Si vous avez suivi la série de tutoriels Django Development, vous aurez une application Django appelée blogsite.

      Créons un dossier pour contenir tous nos scripts de test. Tout d’abord, activez l’environnement virtuel :

      • cd ~/my_blog_app
      • . env/bin/activate

      Ensuite, naviguez vers le répertoire appblogsite, le dossier qui contient les fichiers models.py et views.py, puis créez un nouveau dossier appelé tests :

      • cd ~/my_blog_app/blog/blogsite
      • mkdir tests

      Ensuite, vous transformerez ce dossier en un paquet Python, ajoutez donc un fichier __init__.py :

      • cd ~/my_blog_app/blog/blogsite/tests
      • touch __init__.py

      Vous allez maintenant ajouter un fichier pour tester vos modèles et un autre pour tester vos vues :

      • touch test_models.py
      • touch test_views.py

      Enfin, vous allez créer un scénario de test vide dans test_models.py. Vous devrez importer la classe Django TestCase et en faire une super classe de votre propre classe de test case. Plus tard, vous ajouterez des méthodes à ce scénario de test pour tester la logique de vos modèles. Ouvrez le fichier test_models.py :

      Ajoutez maintenant le code suivant au fichier :

      ~/my_blog_app/blog/blogsite/tests/test_models.py

      from django.test import TestCase
      
      class ModelsTestCase(TestCase):
          pass
      

      Vous avez maintenant ajouté avec succès une séquence de tests à l’appli blogsite. Ensuite, vous remplirez les détails du modèle de cas test vide que vous avez créé ici.

      Étape 2 – Tester votre code Python

      Dans cette étape, vous allez tester la logique du code écrit dans le fichier models.py. En particulier, vous testerez la méthode de sauvegarde du modèle Post afin de vous assurer qu’il crée la bonne portion du titre d’un message lorsqu’il est appelé. 

      Commençons par regarder le code que vous avez déjà dans votre fichier models.py pour la méthode de sauvegarde du modèle Post :

      • cd ~/my_blog_app/blog/blogsite
      • nano models.py

      Vous verrez ce qui suit :

      ~/my_blog_app/blog/blogsite/models.py

      class Post(models.Model):
          ...
          def save(self, *args, **kwargs):
              if not self.slug:
                  self.slug = slugify(self.title)
              super(Post, self).save(*args, **kwargs)
          ...
      

      On peut voir qu’il vérifie si le message sur le point d’être sauvegardé a une valeur de slug, et si ce n’est pas le cas, il appelle slugify pour lui créer une valeur de slug. C’est le type de logique que vous pourriez vouloir tester pour vous assurer que les slugs sont effectivement créés lors de la sauvegarde d’un message.

      Fermez le dossier.

      Pour le tester, retournez à test_models.py :

      Mettez-le ensuite à jour en ajoutant les parties surlignées :

      ~/my_blog_app/blog/blogsite/tests/test_models.py

      from django.test import TestCase
      from django.template.defaultfilters import slugify
      from blogsite.models import Post
      
      
      class ModelsTestCase(TestCase):
          def test_post_has_slug(self):
              """Posts are given slugs correctly when saving"""
              post = Post.objects.create(title="My first post")
      
              post.author = "John Doe"
              post.save()
              self.assertEqual(post.slug, slugify(post.title))
      

      Cette nouvelle méthode test_post_has_slug crée un nouvel article avec le titre « My first post », puis donne à l’article un auteur et l’enregistre. Ensuite, à l’aide de la méthode assertEqual du module Python unittest, il vérifie si le slug du message est correct. La méthode assertEqual vérifie si les deux arguments qui lui sont transmis sont égaux tels que déterminés par l’opérateur « == » et signale une erreur s’ils ne le sont pas.

      Sauvegarder et quitter test_models.py.

      Voici un exemple de ce qui peut être testé. Plus vous ajoutez de logique à votre projet, plus il y a de choses à tester. Si vous ajoutez plus de logique à la méthode de sauvegarde ou créez de nouvelles méthodes pour le modèle Post, vous voudriez ajouter plus de tests ici. Vous pouvez les ajouter à la méthode test_post_has_slug ou créer de nouvelles méthodes de test, mais leurs noms doivent commencer par test.

      Vous avez créé avec succès un cas test pour le modèle Post où vous avez affirmé que les slugs sont correctement créés après la sauvegarde. Dans l’étape suivante, vous rédigerez un scénario de test pour tester les vues.

      Étape 3 – Utiliser le client test de Django

      Dans cette étape, vous allez écrire un scénario de test qui teste une vue en utilisant le client de test Django. Le test client est une classe Python qui agit comme un navigateur web factice, vous permettant de tester vos vues et d’interagir avec votre application Django de la même manière qu’un utilisateur le ferait. Vous pouvez accéder au client test en vous référant à self.client dans vos méthodes de test. Par exemple, créons un cas test dans test_views.py Tout d’abord, ouvrez le fichier test_views.py :

      Ajoutez ensuite ce qui suit :

      ~/my_blog_app/blog/blogsite/tests/test_views.py

      from django.test import TestCase
      
      
      class ViewsTestCase(TestCase):
          def test_index_loads_properly(self):
              """The index page loads properly"""
              response = self.client.get('your_server_ip:8000')
              self.assertEqual(response.status_code, 200)
      

      Le ViewsTestCase contient une méthode test_index_loads_properly qui utilise le client de test Django pour visiter la page d’index du site (http://your_server_ip:8000, où your_server_ip est l’adresse IP du serveur que vous utilisez). Ensuite, la méthode de test vérifie si la réponse a un code de statut de 200, ce qui signifie que la page a répondu sans aucune erreur. Vous pouvez donc être sûr que lorsque l’utilisateur se rendra sur le site, il répondra lui aussi sans erreur.

      Outre le code de statut, vous pouvez lire d’autres propriétés de la réponse du client de test que vous pouvez tester dans la page des réponses de test de la documentation de Django.

      Au cours de cette étape, vous avez créé un scénario de test pour vérifier que la vue rendant la page d’index fonctionne sans erreur. Il y a maintenant deux scénarios de test dans votre séquence de tests. Au cours de l’étape suivante, vous les exécuterez pour voir leurs résultats.

      Étape 4 – Effectuer vos tests

      Maintenant que vous avez terminé la construction d’une séquence de tests pour le projet, il est temps d’exécuter ces tests et de voir leurs résultats. Pour effectuer les tests, naviguez dans le dossier blog (contenant le fichier manage.py de l’application) :

      Puis, exécutez-les :

      Vous verrez un résultat similaire à ce qui suit dans votre terminal :

      Output

      Creating test database for alias 'default'... System check identified no issues (0 silenced). .. ---------------------------------------------------------------------- Ran 2 tests in 0.007s OK Destroying test database for alias 'default'...

      Dans cette sortie, il y a deux points .., dont chacun représente un cas de test réussi. Vous allez maintenant modifier test_views.py pour déclencher un test d’échec. Ouvrez le fichier avec :

      Ensuite, changez le code en surbrillance pour :

      ~/my_blog_app/blog/blogsite/tests/test_views.py

      from django.test import TestCase
      
      
      class ViewsTestCase(TestCase):
          def test_index_loads_properly(self):
              """The index page loads properly"""
              response = self.client.get('your_server_ip:8000')
              self.assertEqual(response.status_code, 404)
      

      Ici, vous avez changé le code de statut de 200 à 404. Maintenant, refaites le test à partir de votre répertoire avec manage.py :

      Vous verrez la sortie suivante :

      Output

      Creating test database for alias 'default'... System check identified no issues (0 silenced). .F ====================================================================== FAIL: test_index_loads_properly (blogsite.tests.test_views.ViewsTestCase) The index page loads properly ---------------------------------------------------------------------- Traceback (most recent call last): File "~/my_blog_app/blog/blogsite/tests/test_views.py", line 8, in test_index_loads_properly self.assertEqual(response.status_code, 404) AssertionError: 200 != 404 ---------------------------------------------------------------------- Ran 2 tests in 0.007s FAILED (failures=1) Destroying test database for alias 'default'...

      Vous voyez qu’il y a un message d’échec descriptif qui vous indique le script, le cas de test et la méthode qui a échoué. Il vous indique également la cause de l’échec, le code de statut n’étant pas égal à 404 dans ce cas, avec le message AssertionError: 200 !  404. L’AssertionError est ici soulevée à la ligne de code surlignée dans le fichier test_views.py :

      ~/my_blog_app/blog/blogsite/tests/test_views.py

      from django.test import TestCase
      
      
      class ViewsTestCase(TestCase):
          def test_index_loads_properly(self):
              """The index page loads properly"""
              response = self.client.get('your_server_ip:8000')
              self.assertEqual(response.status_code, 404)
      

      Il vous indique que l’affirmation est fausse, c’est-à-dire que le code de statut de réponse (200) n’est pas ce à quoi on s’attendait (404). Précédant le message d’échec, vous pouvez voir que les deux points .. sont maintenant passés à . F, qui vous indique que le premier cas test a réussi alors que le second ne l’a pas fait.

      Conclusion

      Dans ce tutoriel, vous avez créé une suite de tests dans votre projet Django, ajouté des scénarios de test au modèle de test et à la logique de visualisation, appris comment exécuter des tests et analysé les résultats des tests. Dans un deuxième temps, vous pouvez créer de nouveaux scripts de test pour le code Python qui n’est pas dansmodels.py et views.py.

      Voici quelques articles qui peuvent s’avérer utiles pour créer et tester des sites web avec Django :

      Vous pouvez également consulter notre page thématique sur Django pour d’autres tutoriels et projets.



      Source link