Un guide pour créer une application de raccourcissement d’URL avec Django

Photo of author

By pierre



La méthode la plus efficace pour maîtriser Django, ou toute autre compétence, réside dans l’application pratique des connaissances acquises à travers la réalisation de projets concrets.

Django se positionne comme le framework de développement web Python le plus répandu. Sa richesse en fonctionnalités intégrées et la vaste collection de paquets tiers disponibles en font un des frameworks web les plus appréciés à l’échelle mondiale.

Il se distingue par sa rapidité, sa fiabilité et une panoplie de fonctionnalités intégrées. Un exemple notable est le système d’authentification prêt à l’emploi, qui vous permet de focaliser vos efforts sur les fonctionnalités essentielles de votre application. De surcroît, l’installation de paquets externes ouvre la voie à des tâches encore plus complexes, à l’instar de Django-allauth, qui facilite l’inscription d’utilisateurs via leurs comptes de réseaux sociaux.

Cependant, il est essentiel de reconnaître que Django est un cadre d’une telle envergure que sa prise en main peut parfois s’avérer complexe.

C’est pourquoi, aujourd’hui, nous allons construire de A à Z une application Django pleinement opérationnelle.

À l’issue de ce tutoriel, vous aurez acquis les compétences suivantes :

  • Création d’une application de raccourcissement d’URL.
  • Compréhension du modèle Django MVT.
  • Maîtrise du flux de travail de création d’un projet.

Prérequis

Les exigences ci-dessous sont facultatives et sont destinées à faciliter le suivi de ce tutoriel. Toutefois, si vous manquez d’expérience dans l’un de ces domaines, ne vous inquiétez pas. La première étape demeure la plus cruciale.

  • Connaissance de base des commandes UNIX (ls, cd, rm, touch).
  • Compréhension des classes et fonctions en Python.
  • Python installé sur votre système (cela peut paraître évident, mais il était essentiel de le mentionner).
  • Une expérience préalable avec Django serait un avantage.

L’ensemble du code source sera accessible sur ce dépôt GitHub.

Maintenant que vous avez une compréhension claire des concepts précédents, entrons dans le vif du sujet.

Description du projet

Dans ce tutoriel, vous allez concevoir un raccourcisseur d’URL. Un raccourcisseur d’URL est, en substance, un service qui prend une URL longue et la transforme en une URL plus concise.

Par exemple, si vous désirez partager un tweet incluant un lien vers votre site web, mais que vous êtes limité par le nombre de caractères, un raccourcisseur d’URL peut s’avérer très pratique.

Illustrons ceci avec un schéma.

Comme vous pouvez le constater, le raccourcisseur d’URL reçoit une URL longue et retourne une version plus courte. C’est exactement ce que nous allons réaliser aujourd’hui.

Grâce à ce projet, vous vous exercerez à l’utilisation du modèle MVT, vous apprendrez les fondamentaux de la conception de bases de données via les modèles Django, et vous découvrirez comment présenter des informations à l’utilisateur à travers les vues, les URL et les templates.

Structure d’un projet Django

Fondamentalement, un site web Django repose sur un projet unique et un ensemble d’applications distinctes. Chacune de ces applications possède des fonctionnalités propres et est capable de fonctionner de manière autonome.

Imaginons une application web complexe telle que Stack Overflow. Son fonctionnement repose sur deux aspects essentiels :

  • La gestion des utilisateurs : connexion, déconnexion, réputation, autorisations.
  • Le forum : questions, réponses, tags, filtres.

En suivant la structure d’un site web Django, le projet serait nommé StackOverflow, et il comprendrait deux applications principales : l’application de gestion des utilisateurs et l’application du forum.

Chacune de ces applications possède ses propres fonctionnalités autonomes. Cela signifie que chaque application contient tout le code nécessaire à son bon fonctionnement.

Ceci inclut les modèles (la structure de la base de données), les vues (les requêtes et les réponses), les schémas d’URL spécifiques, ainsi que les templates et les fichiers statiques (images, CSS, JavaScript). Par conséquent, toute application Django peut être réutilisée, car elle est conçue pour fonctionner indépendamment.

En résumé, un projet fait référence à un ensemble de configurations et d’applications destinées à la création d’une application web. D’autre part, une application Django fait partie intégrante d’un projet, est autonome (possède tous les éléments nécessaires à son fonctionnement) et a pour objectif de réaliser une opération spécifique.

Configuration d’un projet Django

Dans cette section, nous allons configurer un projet Django. Pour ce faire, nous utiliserons divers outils, tels qu’un environnement virtuel pour organiser les dépendances Python, et les scripts Django les plus importants : django-admin et manage.py.

Environnement virtuel

Je recommande vivement l’utilisation d’environnements virtuels lors de la création d’applications avec Django. C’est le moyen le plus efficace de maintenir un ensemble de dépendances spécifique. Son objectif principal est d’isoler les paquets de développement des paquets globaux.

Créons donc un environnement virtuel à l’aide de la commande intégrée de Python.

Remarque : cette méthode requiert Python 3.6 ou une version plus récente pour fonctionner.

python -m venv .venv

Cette commande utilise la commande python -m, ou python –mod. En substance, elle exécute un module, ou une librairie, comme un script. Conformément à la signification de cette commande, venv est la librairie que nous exécutons, et .venv correspond au nom de l’environnement virtuel que nous souhaitons créer.

En termes simples, cette commande signifie :

« Hé Python, exécute la librairie intégrée venv comme un script et crée un environnement virtuel nommé .venv ».

Il est maintenant temps d’activer l’environnement virtuel que nous venons de créer, à l’aide de la commande suivante :

source .venv/bin/activate

Afin de confirmer qu’aucun paquet n’est installé dans le nouveau venv, vous pouvez exécuter :

pip freeze

Si vous avez correctement activé l’environnement virtuel, vous n’obtiendrez aucun résultat. Cela s’explique par le fait que nous n’avons encore rien installé.

Passons à Django

Pour créer notre application de raccourcissement d’URL, commençons par installer le paquet Django. Django étant un paquet tiers, il est nécessaire de l’installer avec Pip (Pip Installs Packages).

$ pip install django
Collecting django
  Downloading Django-3.2.1-py3-none-any.whl (7.9 MB)
     |████████████████████████████████| 7.9 MB 344 kB/s 
Collecting asgiref<4,>=3.3.2
  Using cached asgiref-3.3.4-py3-none-any.whl (22 kB)
Collecting sqlparse>=0.2.2
  Using cached sqlparse-0.4.1-py3-none-any.whl (42 kB)
Collecting pytz
  Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB)
Installing collected packages: asgiref, sqlparse, pytz, django
Successfully installed asgiref-3.3.4 django-3.2.1 pytz-2021.1 sqlparse-0.4.1

Remarque : n’oubliez pas que le signe $ n’est autre que le symbole de votre shell.

Afin de vérifier que l’installation s’est déroulée avec succès, nous allons à nouveau examiner les paquets installés de notre venv.

$ pip freeze
asgiref==3.3.4
Django==3.2.1
pytz==2021.1
sqlparse==0.4.1

Ne vous inquiétez pas si les versions que vous obtenez diffèrent des miennes. Tant que Django est toujours en version 3.x, vous pouvez continuer sans problème.

Démarrage d’un projet Django

Une fois Django installé, il est temps de créer la structure du site web du raccourcisseur d’URL. Vous souvenez-vous de ce qu’est un projet Django ? Créons-en un en exécutant la commande suivante :

django-admin startproject config

Pour expliquer cette commande, django-admin est un utilitaire de ligne de commande qui effectue toutes les tâches nécessaires à la création d’un projet Django. La partie « startproject » est la commande exécutée par l’utilitaire django-admin, et config est le nom du projet que nous allons créer.

Il est important de souligner que config peut être remplacé par le nom de votre choix. La raison pour laquelle j’utilise config comme nom de ce projet est simplement une question de commodité. Il est plus aisé de passer d’un projet à l’autre en conservant toujours la même convention de nommage. N’hésitez donc pas à utiliser d’autres noms de projets quand vous le souhaitez.

Comme vous pouvez le remarquer, un dossier config/ est maintenant créé, et celui-ci contient plusieurs fichiers. Nous étudierons la structure des fichiers du projet plus tard. Pour l’instant, entrons dans le répertoire du projet et exécutons le serveur local.

cd config/

Le fichier le plus important que vous utiliserez est le script manage.py. Il possède les mêmes fonctionnalités que django-admin, mais le principal avantage de son utilisation réside dans sa capacité à gérer les paramètres lors de l’exécution du projet.

Vérifions maintenant si tout fonctionne correctement.

python manage.py runserver

Création de l’application de raccourcissement d’URL

Il est temps de créer l’application principale du projet. Nous allons utiliser le fichier manage.py pour mener à bien cette tâche.

python manage.py startapp urlshortener

Cela crée une application Django, nommée urlshortener. Si vous exécutez la commande tree, vous obtiendrez une structure similaire :

.
├── config
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
└── urlshortener
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

Clarifions les différents fichiers qui ont été créés jusqu’à présent. « config » est le nom de notre projet, et il a été nommé de cette façon par convention. À l’intérieur de config, vous trouverez le fichier settings.py, qui est l’endroit où vous définissez tous les paramètres de votre projet. Le fichier urls.py est la configuration globale des URL à l’intérieur du projet. Il définit les chemins URL de toutes les applications au sein du projet.

Ne vous souciez pas trop des fichiers asgi.py et wsgi.py. Ce sont des fichiers qui vous permettent de configurer votre application lors de son déploiement.

Le fichier manage.py est le script Python qui vous permet d’exécuter toutes les commandes disponibles de Django-admin.

Si vous jetez un coup d’œil à l’intérieur du dossier urlshortener, qui est le nom de l’application que vous venez de créer, vous remarquerez peut-être la présence d’un dossier étrange nommé « migrations/ » et d’autres fichiers essentiels au fonctionnement de toute application.

Le fichier apps.py est l’emplacement où se trouve la configuration de l’application. En général, vous n’y apporterez pas de modifications, sauf si vous réalisez des tâches assez avancées.

Le fichier admin.py est l’endroit où vous enregistrez vos modèles afin de les rendre visibles dans le panneau d’administration de Django.

Le fichier models.py est le plus important. Dans ce module, vous définissez les modèles, qui (en termes simples) déterminent la manière dont les données sont stockées. Vous en apprendrez davantage sur les modèles par la suite.

Le dossier migrations/ est l’endroit où sont stockées les migrations Django. Nous y reviendrons plus en détail ultérieurement.

Le fichier tests.py est l’endroit où sont stockés les tests. Nous ne couvrirons pas les tests dans ce tutoriel.

Le fichier views.py est celui qui stocke les vues. En substance, il définit la façon dont l’utilisateur interagira avec tous les aspects de votre application.

Installation d’une application Django

Avant de continuer, ouvrez le fichier settings.py et modifiez la variable INSTALLED_APPS en ajoutant l’application urlshortener.

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Custom apps
    'urlshortener',
]

Il s’agit d’une procédure courante lors de la création d’une application. Par conséquent, à chaque fois que vous en créez une, n’oubliez pas de l’installer dans les paramètres du projet.

Compréhension du modèle MVT

Le modèle Model, View, Template est le modèle de conception logicielle que les développeurs Django utilisent pour la création d’applications web.

Il repose sur 3 concepts clés. Modèle (données), Vue (Interaction de l’utilisateur avec les données), Template (Comment les utilisateurs voient les données).

Les modèles sont des classes Python qui définissent tous les champs et les comportements des données que vous souhaitez stocker. En règle générale, chaque modèle correspond à une table unique dans la base de données.

Les vues, dans leur expression la plus simple, sont des fonctions qui reçoivent une requête de l’utilisateur et génèrent une réponse. La logique métier intervient entre ces deux étapes. Je suis conscient que la « logique métier » est un concept assez vague, alors permettez-moi de vous expliquer exactement ce qu’elle représente. La logique métier est la manière dont les données sont créées, stockées et supprimées, tout simplement.

Enfin, les templates sont des documents texte (généralement HTML) qui sont présentés aux utilisateurs. Leur rôle est de présenter les données de la manière la plus claire possible. Django intègre un mini-langage appelé Django Template Language (DTL) qui vous permet d’incorporer une partie de la puissance de Python dans les documents texte.

Création du modèle Shortener

Maintenant que vous avez une bonne compréhension du modèle MVT, passons à la création du raccourcisseur d’URL Django de A à Z.

Tout d’abord, définissons le modèle de raccourcisseur dans le fichier models.py.

'''
Url shortener model
'''

from django.db import models

# Create your models here.

class Shortener(models.Model):
    '''
    Creates a short url based on the long one
    
    created -> Hour and date a shortener was created 
    
    times_followed -> Times the shortened link has been followed

    long_url -> The original link

    short_url ->  shortened link https://domain/(short_url)
    ''' 
    created = models.DateTimeField(auto_now_add=True)

    times_followed = models.PositiveIntegerField(default=0)    

    long_url = models.URLField()

    short_url = models.CharField(max_length=15, unique=True, blank=True)

    class Meta:

        ordering = ["-created"]


    def __str__(self):

        return f'{self.long_url} to {self.short_url}'

Je sais, il s’agit d’une classe assez conséquente, avec de nombreux éléments étranges, mais ne vous inquiétez pas. Je vais examiner chaque élément important étape par étape.

Explication du modèle

Pour commencer, nous importons le module de modèles. Ce module contient toutes les fonctionnalités nécessaires à la création d’un modèle Django.

En examinant le modèle « Shortener », la première chose à noter est qu’il hérite de models.Model. En effet, tout modèle dans toute application Django doit être une sous-classe de la classe models.Model.

Ensuite, nous définissons tous les champs que le modèle possédera dans la base de données. Le champ « created » représente la date et l’heure de création du lien raccourci. Nous utilisons donc DateTimeField pour créer ce type de fonctionnalité. Nous utilisons l’argument auto_now_add=True, car nous souhaitons que le champ ne soit modifié que lors de la création de l’instance.

Le deuxième champ, times_followed, fait référence au nombre de fois où l’URL raccourcie a été utilisée. Il s’agit d’un PositiveIntegerField, et nous spécifions une valeur par défaut de zéro. Cela signifie qu’à chaque fois qu’une instance est créée, Django remplira ce champ avec la valeur 0.

D’autre part, long_url fait référence à l’URL saisie par l’utilisateur. Il s’agit d’un URLField, car nous voulons que l’utilisateur ne saisisse que des caractères de la forme : http://votresite.com.

Le dernier champ est short_url, et il comporte des détails intéressants. Nous précisons qu’il ne peut contenir que 15 caractères, qu’il doit être unique, ce qui signifie qu’il ne peut y avoir d’éléments répétés dans ce champ. Enfin, nous indiquons qu’il peut être laissé vide, ce qui implique que lors de l’utilisation de formulaires, les utilisateurs n’auront pas à saisir leur propre code de raccourcissement.

La classe interne Meta nous indique comment la classe doit se comporter, et nous précisons que l’ordre (en appelant Shortener.objects.all()) des objets de raccourcissement sera classé par les plus récents.

La méthode __str__ définit la façon dont le modèle doit être affiché. Ainsi, si nous avons un objet avec long_url = « https://toptips.fr.com/ » et la partie raccourcie « 123456 », et que nous l’affichons, nous obtiendrons :

https://toptips.fr.com/ to 123456

Il est maintenant temps de trouver une méthode permettant de sauvegarder aléatoirement le lien court.

Création d’une fonctionnalité de raccourcissement

Nous allons créer deux fonctions personnalisées. La première générera un code aléatoire, et la seconde empêchera d’obtenir des codes aléatoires répétés du modèle Shortener. Pour ce faire, créez un fichier utils.py dans l’application « urlshortener ».

touch utils.py

Dans ce fichier, nous utiliserons la fonction choose du module random intégré. Cela facilite la sélection de caractères aléatoires pour créer le code.

'''
Utilities for Shortener
'''
from django.conf import settings

from random import choice

from string import ascii_letters, digits

# Try to get the value from the settings module
SIZE = getattr(settings, "MAXIMUM_URL_CHARS", 7)

AVAIABLE_CHARS = ascii_letters + digits


def create_random_code(chars=AVAIABLE_CHARS):
    """
    Creates a random string with the predetermined size
    """
    return "".join(
        [choice(chars) for _ in range(SIZE)]
    )

Comme vous pouvez le voir, cette fonction renvoie une chaîne aléatoire de la longueur spécifiée dans le fichier de paramètres, ou 7 par défaut. Vous utilisez la fonction getattr pour obtenir une variable du module de paramètres, mais sans générer d’erreur si la variable n’est pas spécifiée.

Faisons quelques calculs. Si nous avons 7 emplacements où il peut y avoir jusqu’à 62 caractères disponibles pour chaque emplacement, le nombre possible de permutations est :

Ainsi, sur la base de ces calculs rapides, la partie raccourcie peut être remplie jusqu’à 2,5 billions de codes différents. Nous pouvons donc écarter le risque de manquer d’URL raccourcies aléatoires.

Bien qu’un tel nombre de permutations soit possible, il existe une faible probabilité d’obtenir des parties raccourcies répétées. Cela pose problème, car nous avons configuré le champ shortened_url pour qu’il soit unique. C’est pourquoi la fonction suivante est si utile.

def create_shortened_url(model_instance):
    random_code = create_random_code()
    # Gets the model class

    model_class = model_instance.__class__

    if model_class.objects.filter(short_url=random_code).exists():
        # Run the function again
        return create_shortened_url(model_instance)

    return random_code

Voyons ce qui se passe ici. La fonction prend en argument une instance de modèle « Shortener ». Tout d’abord, la fonction génère un code aléatoire à l’aide de la fonction create_random_code. Ensuite, elle obtient la classe du modèle et vérifie s’il existe un autre objet ayant la même valeur pour short_url. Si c’est le cas, elle s’exécute à nouveau, mais si tout va bien, elle renvoie le random_code.

Plus tard, vous interagirez avec le shell, afin d’étudier de plus près cette fonction.

Après avoir créé la fonction utilitaire, utilisons-la pour créer des codes aléatoires dans le modèle de raccourcisseur.

Modification de la méthode de sauvegarde

À la fin de la classe « Shortener », vous allez modifier la méthode de sauvegarde du modèle. La méthode save est appelée à chaque fois qu’un objet est enregistré dans la base de données. Nous allons donc voir comment l’utiliser ici.

# Import the function used to create random codes
from .utils import create_shortened_url

# At the end of the  Shortener model
    def save(self, *args, **kwargs):

        # If the short url wasn't specified
        if not self.short_url:
            # We pass the model instance that is being saved
            self.short_url = create_shortened_url(self)

        super().save(*args, **kwargs)

La méthode save est surchargée, ce qui signifie que vous introduisez une nouvelle fonctionnalité dans une méthode parent préexistante. Il s’agit essentiellement de demander à Django que chaque fois qu’un objet « Shortener » est enregistré et que short_url n’est pas spécifié, il doit être rempli avec un code aléatoire.

Exécution des migrations

Il est maintenant temps de créer et d’exécuter les migrations du modèle Shortener. Pour ce faire, exécutez les commandes suivantes dans le dossier racine du projet.

$ python manage.py makemigrations
Migrations for 'urlshortener':
  urlshortener/migrations/0001_initial.py
    - Create model Shortener

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, urlshortener
Running migrations:
  ......
  # Apply the URL shortener migrations
  Applying urlshortener.0001_initial... OK

Pour l’instant, vous n’avez pas à vous préoccuper de ce que sont les migrations. Retenez que lors de l’exécution de ces deux commandes, Django crée un fichier de base de données db.sqlite, basé sur les modèles que vous avez définis.

Créons quelques objets avec le shell Django.

$ python manage.py shell

>>> from urlshortener.models import Shortener
>>> s = Shortener(long_url="https://toptips.fr.com")
>>> s.short_url
''
>>> s.save()
>>> s.short_url
'kdWFVIc'
>>> s.long_url
'https://toptips.fr.com'
>>> print(s)
https://toptips.fr.com to kdWFVIc

Voici en résumé le fonctionnement des objets raccourcisseurs.

Écriture des vues

Comme je l’ai déjà mentionné, une vue est une simple fonction qui prend une requête et renvoie une réponse. Voyons donc comment créer une vue Hello World.

Modèle de réponse de base

Dans le fichier « urlshortener/views.py », créez une fonction home_view.

'''
Shortener views
'''
from django.shortcuts import render, get_object_or_404 # We will use it later

from django.http import HttpResponse 

# Create your views here.

def home_view(request):
    return HttpResponse("Hello world")

Elle renvoie un simple message « Hello World ». Vous verrez plus tard comment cela se présente dans le navigateur. Créez maintenant un fichier « urls.py », qui contiendra tous les schémas d’URL de l’application.

toucher urls.py

Ajoutez le code suivant :

'''
Urls for shortener app urlshortener/urls.py
'''

from django.urls import path

# Import the home view
from .views import home_view

appname = "shortener"

urlpatterns = [
    # Home view
    path("", home_view, name="home")
]

La variable appname déclare (comme son nom l’indique) l’espace de noms de l’application urlshortener.

Pour résumer rapidement, nous importons la fonction path, qui retourne un élément à inclure dans les urlpatterns de l’application. L’attribut name est l’espace de noms du chemin, qui peut être appelé au sein des templates si nécessaire.

Modifions maintenant les URL globales du projet.

# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    
    # Shortener Urls
    path('', include('urlshortener.urls'))
]

Relançons maintenant le serveur.

python manage.py runserver

Si vous exécutez le serveur, vous obtiendrez un simple message « Hello world ». En effet, vous incluez les schémas d’URL de l’application de raccourcissement d’URL dans le projet global.

Ce n’est qu’un point de départ. Il est maintenant temps de créer un formulaire afin de permettre à l’utilisateur de créer lui-même des URL raccourcies.

Création de formulaires

Dans Django, un formulaire est une simple classe qui permet de récupérer une saisie de l’utilisateur.

Vous allez créer un fichier forms.py. La convention veut que tous les formulaires de l’application soient stockés dans ce fichier.

cd urlshortener/
touch forms.py

Dans ce fichier, vous allez créer une classe « ShortenerForm » qui hérite de « ModelForm ».

'''
Shortener Forms urlshortener/forms.py
'''

from django import forms

from .models import Shortener

class ShortenerForm(forms.ModelForm):
    
    long_url = forms.URLField(widget=forms.URLInput(
        attrs={"class": "form-control form-control-lg", "placeholder": "Your URL to shorten"}))
    
    class Meta:
        model = Shortener

        fields = ('long_url',)

Il s’agit d’un formulaire de modèle, car son rôle est de créer un objet de modèle à partir de la saisie de l’utilisateur. Nous utilisons également l’argument widget, qui nous permet de spécifier l’attribut « class » (classe en CSS, et non en Python). En effet, nous allons styliser l’application à l’aide de Bootstrap ultérieurement.

Finalisation des vues

Une fois les formulaires créés, il est temps de définir la logique métier finale de l’application.

Accédez au fichier views.py de l’application de raccourcissement et modifiez la vue home_view. Vous pouvez consulter le <a href= »https://github.com/Daniel1404/Django-Url-Shortener/blob/main/config/urlshortener/views.py » rel= »nofollow noopener