Construire une newsletter par e-mail avec Django et Twilio SendGrid

January 17, 2020
Rédigé par
Philip Kiely
Contributeur
Les opinions exprimées par les contributeurs de Twilio sont les leurs

Construire une newsletter par e-mail avec Django et Twilio SendGrid

Ces dernières années, l'envoi de newsletters par e-mail est devenu un outil de plus en plus populaire auprès des créateurs de contenu désireux d'atteindre leur public. En matière de développement de logiciels, des newsletters telles que la Sidebar de Sacha Greif ou la désormais multicanale Cooper Press ont rencontré un franc succès en diffusant des sélections de liens et des articles originaux. Un certain nombre de services permettent de résoudre la myriade d'obstacles techniques et non techniques à la fiabilité de la distribution dans le cas de vastes listes de diffusion. On compte ainsi parmi les services existants la solution officielle propriétaire et les ressources sur la création de newsletters de Twilio SendGrid. Bien que ce que nous développons dans ce tutoriel ne soit pas aussi complet qu'un produit clé en main, nous allons aujourd'hui nous plonger dans la création de notre propre back-end minimaliste de newsletter par e-mail à l'aide du framework Web Django de Python et de l' API d'envoi d'e-mails de base de Twilio SendGrid.

Configuration requise pour le tutoriel

Pour suivre l'ensemble de ce tutoriel, vous aurez besoin des éléments suivants :

  • Python 3.6 ou version ultérieure. Si vous n'avez pas encore installé d'interpréteur Python, vous pouvez vous rendre sur python.org pour télécharger un programme d'installation.
  • Django. Nous installerons Django plus tard pour développer notre application Web.
  • Au moins deux adresses e-mail actives pouvant recevoir des e-mails.
  • Un compte Twilio SendGrid (remarque : ce type de compte est différent d'un compte Twilio). Vous pouvez vous connecter ici ou créer un compte gratuit et consulter les ressources gratuites fournies avec votre nouveau compte.

Si vous le souhaitez, n'hésitez pas à télécharger le projet terminé sur GitHub et à vous en servir pour le reste de ce tutoriel. Le fichier README contient des instructions de configuration modifiées pour le code fini.

Création d'un environnement virtuel Python

Conformément aux bonnes pratiques Python, nous allons développer notre application dans son propre répertoire et environnement virtuel. Ensuite, nous installerons nos packages Python et créerons notre projet Django.

Si vous utilisez un système Unix ou MacOS, vous pouvez procéder en ouvrant un terminal et en exécutant les commandes suivantes :

$ mkdir sendgrid-newsletter
$ cd sendgrid-newsletter
$ python -m venv sendgrid-newsletter-venv
$ source sendgrid-newsletter/bin/activate
(sendgrid-newsletter) $ pip install django sendgrid

Sous Windows, vous pouvez faire de même avec l'invite de commande :

$ md sendgrid-newsletter
$ cd sendgrid-newsletter
$ python -m venv sendgrid-newsletter-venv
$ sendgrid-newsletter-venvScripts\activate
(sendgrid-newsletter) $ pip install django sendgrid

La dernière ligne utilise pip, le programme d'installation du package Python, pour installer les deux packages du projet :

Au moment où j'écris cet article, ce tutoriel a été testé sur les versions de package suivantes, incluses dans le fichier requirements.txt du projet terminé :

asgiref==3.2.3
Django==3.0.2
python-http-client==3.2.1
pytz==2019.3
sendgrid==6.1.0
sqlparse==0.3.0

Configuration de Twilio SendGrid

Une fois connecté à Twilio SendGrid, rendez-vous sur la page des clés API. Cliquez sur « Create an API Key » (Créer une clé API).

Capture d'écran Clé API de création SendGrid

Vous devriez donner à votre clé API un nom significatif tel que « Ma Newsletter Django ». J'ai créé ma clé avec « Full Access » (Accès complet) de sorte qu'elle puisse effectuer n'importe quelle action sur mon compte ; si vous voulez une clé à accès limité, vous pouvez configurer les options vous-même après avoir créé une clé avec « Restricted Access » (Accès restreint). Cliquez sur le bouton « Create & View » (Créer et afficher) pour obtenir votre clé. Copiez-la dans un fichier sécurisé. Si vous perdez votre clé, vous devrez en créer une nouvelle. Vous devrez définir une variable d'environnement SENDGRID_API_KEY égale à la valeur de la chaîne copiée, car c'est ainsi que le programme Django accédera à la clé. Définir une variable d'environnement est facile sous MacOS, Linux et Windows, comme expliqué ici.

Création d'un back-end de newsletter par e-mail

Maintenant que nous avons terminé la configuration, rentrons dans le vif du sujet : la création de notre application avec Django. Avant de commencer à coder, passons en revue ce que l'on attend du logiciel.

En formulant les exigences comme des scénarios d'utilisation, nous constatons que le logiciel doit permettre d'accomplir quatre tâches principales :

  1. Un nouvel abonné doit pouvoir saisir son adresse e-mail dans un formulaire, recevoir une confirmation et cliquer dessus pour confirmer son abonnement.
  2. Un abonné existant doit pouvoir se désabonner à l'aide d'un lien personnalisé.
  3. L'administrateur doit être en mesure de télécharger et d'envoyer un fichier sous la forme d'un e-mail formaté.
  4. L'administrateur doit pouvoir accéder à un tableau de bord pour visualiser les abonnés et les e-mails envoyés.

Bien que cette liste semble considérable, les fonctionnalités intégrées de Django et de SendGrid rendent la chose plus facile que ce que vous pensez.

Configuration de Django

Django fournit un bon échafaudage pour le projet avec la commande django-admin startproject PROJECTNAME. Ensuite, dans le répertoire créé, nous utiliserons python manage.py startapp APPNAME pour terminer le code passe-partout avec une application Django. D'un point de vue conceptuel, un projet peut contenir une ou plusieurs applications, chacune ayant un code pour les routes, les modèles et les vues. Cette application est simple et utilisera une architecture mono-application pour plus de simplicité, bien que des programmes plus grands puissent intégrer du code commun dans des applications distinctes. Les deux commandes liées aux migrations traiteront la configuration initiale de la base de données et créeront une base de données basée sur un fichier à l'aide du moteur SQLite, que vous pouvez, si vous le souhaitez, permuter dans les paramètres de PostgreSQL ou autre système similaire. Dans votre environnement et votre répertoire, exécutez :

django-admin startproject newsletter
cd newsletter
python manage.py startapp core
python manage.py makemigrations
python manage.py migrate

Dans un projet Django, vous devez enregistrer vos applications avec les paramètres principaux. Dans newsletter/settings.py, ajoutez le nom de l'application 'core' à la fin de la liste INSTALLED_APPS. Si ce projet comprenait plusieurs applications, vous devriez inclure chacune d'elles dans cette liste. Voici à quoi la liste INSTALLED_APPS devrait ressembler après vos modifications :

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'core',
]

Pendant que nous modifions les paramètres, configurons les deux entrées dont nous aurons besoin pour utiliser SendGrid et l'URL à inclure dans les liens envoyés par e-mail. En supposant que vous ayez parcouru le reste de la configuration, voici ce que vous devrez ajouter à la fin de newsletter/settings.py :

FROM_EMAIL = 'newsletter@example.com' # replace with your address
SENDGRID_API_KEY = os.environ.get('SENDGRID_API_KEY')

Notez que le paramètre FROM_EMAIL devrait être remplacé par une adresse e-mail réelle à partir de laquelle vous pouvez envoyer et recevoir des e-mails.

Pour finir, nous allons créer un superutilisateur qui administrera l'application. Ce superutilisateur désigne l'utilisateur qui envoie la newsletter par e-mail et a accès au panneau d'administration. Depuis votre terminal, exécutez ce qui suit :

python manage.py createsuperuser

L'interface de ligne de commande vous guidera tout au long de la sélection d'un nom d'utilisateur, d'une adresse e-mail et d'un mot de passe pour le superutilisateur.

Une fois la structure du projet en place, nous allons parcourir individuellement les quatre flux utilisateurs.

Ajout d'abonnés

Pour créer une liste d'abonnés, nous avons d'abord besoin d'un moyen de représenter les abonnés dans la base de données. Nous pouvons utiliser le fichier models.py de Django dans l'application core pour créer un modèle. Pour chaque abonné, nous enregistrons son adresse e-mail, une valeur booléenne de confirmation d'adresse e-mail et un nombre aléatoire servant à confirmer ou à supprimer l'adresse e-mail. Ces données sont représentées comme suit dans core/models.py :

from django.db import models

class Subscriber(models.Model):
    email = models.EmailField(unique=True)
    conf_num = models.CharField(max_length=15)
    confirmed = models.BooleanField(default=False)

    def __str__(self):
        return self.email + " (" + ("not " if not self.confirmed else "") + "confirmed)"

Chaque modèle Django a une fonction __str__ qui génère une représentation de chaîne des données pour chaque instance. Nous l'utiliserons dans le panneau d'administration que nous configurerons dans un instant. Notez également que conf_num, qui est un code de vérification utilisé lors de la confirmation de l'abonné, est stocké comme une représentation d'un nombre en tant que chaîne, soit un format plus pratique à manier.

Chaque fois que vous ajoutez ou modifiez un modèle, vous devez migrer votre base de données pour gérer le nouveau schéma de données. Pour ce faire, après avoir créé le modèle d'abonné, exécutez ce qui suit :

python manage.py makemigrations
python manage.py migrate

Nous sommes maintenant prêts à configurer le panneau d'administration. Les puissantes fonctionnalités que Django offre par défaut vont nous permettre d'administrer la newsletter par e-mail. Tout d'abord, nous devons enregistrer le modèle d'abonné Subscriber dans le fichier core/admin.py de la façon suivante :

from django.contrib import admin
from .models import Subscriber

admin.site.register(Subscriber)

Ensuite, exécutez le serveur avec ce qui suit :

python manage.py runserver

Rendez-vous à l'adresse http://127.0.0.1:8000/admin/ et connectez-vous à l'aide des informations d'identification de superutilisateur créées précédemment.

Capture d'écran Interface d'administration Django

Ce tableau de bord inclut les fonctions de création, de lecture, de mise à jour et de suppression, sans configuration nécessaire, pour tous les modèles. Vous pouvez le tester en cliquant sur l'entrée « Subscribers » (Abonnés) pour vous rendre à l'adresse http://127.0.0.1:8000/admin/core/subscriber/ et en utilisant le bouton « Add Subscriber » (Ajouter un abonné) dans le coin supérieur droit de l'écran pour ajouter un abonné.

Capture d'écran Ajouter un abonné

Cette section a toutefois pour but de créer une page permettant aux gens de s'inscrire eux-mêmes. Pour ce faire, nous devons créer une vue, ce qui passe d'abord par la définition d'une route. Dans newsletter/urls.py, nous ajoutons une URL /new/ sous l'URL /admin/ existante :

from django.contrib import admin
from django.urls import path
from core import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('new/', views.new, name='new'),
]

L'interface utilisateur pour la gestion des abonnés est assez simple. Elle se compose d'un formulaire avec un seul champ pour l'adresse e-mail. Lorsqu'un abonné potentiel consulte l'URL /new/, il peut utiliser le formulaire pour ajouter son adresse e-mail en tant qu'abonné. Cependant, nous ne voulons pas que des personnes s'abonnent avec une adresse qui n'est pas la leur. C'est pourquoi nous utiliserons SendGrid pour envoyer un e-mail de confirmation. Réglez core/views.py comme suit :

from django.shortcuts import render
from django.http import HttpResponse
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from .models import Subscriber
from .forms import SubscriberForm
import random
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

# Helper Functions
def random_digits():
    return "%0.12d" % random.randint(0, 999999999999)

@csrf_exempt
def new(request):
    if request.method == 'POST':
        sub = Subscriber(email=request.POST['email'], conf_num=random_digits())
        sub.save()
        message = Mail(
            from_email=settings.FROM_EMAIL,
            to_emails=sub.email,
            subject='Newsletter Confirmation',
            html_content='Thank you for signing up for my email newsletter! \
                Please complete the process by \
                <a href="{}/confirm/?email={}&conf_num={}"> clicking here to \
                confirm your registration</a>.'.format(request.build_absolute_uri('/confirm/'),
                                                    sub.email,
                                                    sub.conf_num))
        sg = SendGridAPIClient(settings.SENDGRID_API_KEY)
        response = sg.send(message)
        return render(request, 'index.html', {'email': sub.email, 'action': 'added', 'form': SubscriberForm()})
    else:
        return render(request, 'index.html', {'form': SubscriberForm()})

Comme il s'agit d'un fragment de code assez long, nous allons le décomposer en plusieurs portions. La fonction new() sera appelée lorsque l'utilisateur visitera l'URL /new/ sur son navigateur, à la fois pour les requêtes GET et les requêtes POST. Dans une requête POST, déclenchée par la soumission d'un formulaire, nous commençons par créer un objet Subscriber selon notre modèle de données, en utilisant l'adresse e-mail soumise avec le formulaire et un nombre aléatoire à 12 chiffres (avec des zéros à gauche si nécessaire). Après avoir enregistré l'abonné dans la base de données, nous créons et envoyons un e-mail avec un lien de confirmation à l'aide des paramètres SendGrid configurés précédemment. La fonction request.build_absolute_uri() garantit que l'URL absolue est correcte à la fois dans l'environnement local et dans un environnement déployé. Elle renvoie ensuite la page Web pour que l'utilisateur puisse saisir une autre adresse e-mail. Sinon, si la page est chargée pour la première fois en visitant l'URL comme on le ferait d'ordinaire, ce qui aurait pour effet de déclencher une requête GET, il s'agit simplement de rendre la page index.html que nous sommes sur le point d'écrire.

Vous avez peut-être remarqué que la page que nous rendons repose sur un élément nommé SubscriberForm représentant le formulaire Web qui apparaîtra sur la page HTML. Nous pouvons définir ce formulaire dans core/forms.py, soit un nouveau fichier qui doit être créé :

from django import forms

class SubscriberForm(forms.Form):
    email = forms.EmailField(label='Your email',
                             max_length=100,
                             widget=forms.EmailInput(attrs={'class': 'form-control'}))

Pour finir, nous avons besoin d'une page Web qui permettra aux gens d'ajouter leurs e-mails. Avec une simple touche de Bootstrap 4, cette page présente un design minimaliste, mais permet de créer un modèle de base. Tout d'abord, créez un répertoire core/templates. Ensuite, créez dans ce dossier un fichier index.html, qui répondra à tous nos besoins en matière de modèle. Collez ces contenus :

<!doctype html>
<html>
    <head>
        <title> Email Newsletter </title>
        <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    </head>
    <body>
        <div class="container">
            <div class="col-12">
                <h1>Email Newsletter</h1>
            </div>
            <div class="col-12">
                {% if email %}
                <p>{{ email }} has been {{ action }}.</p>
                {% endif %}
            </div>
        {% if form %}
            <div class="col-12 col-md-4">
                <form method="post" novalidate>
                    {% csrf_token %}
                    {{ form }}
                    <br>
                    <button type="submit" class="btn btn-success">Subscribe!</button>
                </form>
            </div>
        {% endif %}
        </div>
    </body>
</html>

Si vous avez arrêté le serveur, redémarrez-le, puis rendez-vous sur http://127.0.0.1:8000/new/ et saisissez votre adresse e-mail dans le formulaire.

Page d&#x27;abonnement

En supposant que tout est configuré correctement et que vous avez utilisé une adresse e-mail valide, vous devriez recevoir un e-mail de confirmation dans un délai d'une minute environ (consultez votre dossier de spam). Avant de cliquer sur le lien de confirmation, nous devons ajouter la vue confirm dans le fichier core/views.py :

def confirm(request):
    sub = Subscriber.objects.get(email=request.GET['email'])
    if sub.conf_num == request.GET['conf_num']:
        sub.confirmed = True
        sub.save()
        return render(request, 'index.html', {'email': sub.email, 'action': 'confirmed'})
    else:
        return render(request, 'index.html', {'email': sub.email, 'action': 'denied'})

Vous remarquerez peut-être que cette vue utilise une requête « GET » même si elle modifie la base de données. Ce n'est pas comme cela que les méthodes HTTP sont censées fonctionner ! Cependant, sachant que le lien de confirmation est inclus dans un e-mail plutôt que dans une requête générée par un formulaire, nous devons utiliser une requête « GET » afin de la déclencher depuis le navigateur en cas de clic sur le lien dans l'e-mail. Nous nous écarterons à nouveau de la convention pour le lien « Unsubscribe » (Se désabonner) que nous créerons dans la section suivante.

Notez par ailleurs que nous vérifions le numéro de confirmation (fourni comme paramètre de requête dans l'URL) avant de marquer l'adresse comme confirmée. C'est ce qui permet de prouver que la personne a effectivement reçu un e-mail de notre part. Cependant, il ne s'agit pas vraiment d'une fonction de sécurité car les données sont stockées et transmises en texte brut, et ces numéros de confirmation aléatoires ne doivent pas être traités comme des mots de passe ou tout autre facteur d'authentification fort. Lorsque la sécurité est importante, une méthode plus robuste consiste à utiliser un cryptage de bout en bout avec un serveur Web HTTP sécurisé, un certificat SSL et un jeton Web JSON à courte durée d'expiration.

Ajoutez l'URL /confirm/ à la liste urlpatterns dans newsletter/urls.py :

urlpatterns = [
    path('admin/', admin.site.urls),
    path('new/', views.new, name='new'),
    path('confirm/', views.confirm, name='confirm'),
]

Maintenant que le serveur est en cours d'exécution, vous pouvez enfin cliquer sur le lien dans l'e-mail. Félicitations ! Vous avez configuré une méthode de création et de confirmation des abonnés.

Suppression d'abonnés

Si vous envoyez un e-mail de marketing ou autre envoi de masse, vous devriez inclure au bas de l'e-mail un lien donnant la possibilité aux destinataires de se désabonner. Techniquement, cela marche presque de la même façon que la fonction confirm, la seule différence étant que l'abonné est supprimé au lieu d'être confirmé. Le code dans core/views.py est le suivant :

def delete(request):
    sub = Subscriber.objects.get(email=request.GET['email'])
    if sub.conf_num == request.GET['conf_num']:
        sub.delete()
        return render(request, 'index.html', {'email': sub.email, 'action': 'unsubscribed'})
    else:
        return render(request, 'index.html', {'email': sub.email, 'action': 'denied'})

Ajoutez l'URL au tableau urlpatterns dans newsletter/urls.py :

urlpatterns = [
    path('admin/', admin.site.urls),
    path('new/', views.new, name='new'),
    path('confirm/', views.confirm, name='confirm'),
    path('delete/', views.delete, name='delete'),
]

Comme pour la fonction de confirmation, il s'agit d'une requête « GET » même si la méthode HTTP utilisée n'est pas la bonne, car il doit s'agir d'un lien cliquable via un navigateur, et parce que le numéro de confirmation est en texte brut et ne constitue donc pas une fonction de sécurité.

Envoi de newsletters

Maintenant que vous avez votre liste d'abonnés, vous allez leur envoyer le contenu remarquable et pertinent auquel ils ont souscrit. Même si nous pourrions construire des pages Web dans l'application principale pour gérer le téléchargement et l'envoi de newsletters, nous allons plutôt approfondir l'utilisation des fonctionnalités plus avancées du panneau d'administration qui géreront une grande partie de ce travail pour nous.

Avant de commencer à programmer, nous allons avoir besoin d'un emplacement où stocker les fichiers téléchargés. Django offre un moyen générique de stocker les téléchargements de fichiers, documenté ici. Créez un dossier à la racine du projet (le même répertoire que celui contenant manage.py) et appelez-le uploaded_newsletters/. Ensuite, ajoutez MEDIA_URL = 'uploaded_newsletters/' à votre settings.py juste en-dessous de la variable STATIC_URL. Le contenu de la newsletter que l'administrateur télécharge sera stocké dans ce répertoire uploaded_newsletters/.

Tout d'abord, nous avons besoin d'un moyen de représenter les newsletters dans la base de données. Pour ce faire, retour sur core/models.py pour créer un modèle Newsletter ! Comme il sera utile de savoir quand chaque newsletter aura été créée et mise à jour, il y aura deux champs date/heure représentant ces valeurs. Chaque newsletter a besoin d'un sujet, d'une chaîne destinée à la ligne d'objet de l'e-mail et de contenu, sous la forme d'un fichier qui sera téléchargé dans le dossier multimédia que nous venons de créer. Le modèle à représenter est :

class Newsletter(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    subject = models.CharField(max_length=150)
    contents = models.FileField(upload_to='uploaded_newsletters/')

    def __str__(self):
        return self.subject + " " + self.created_at.strftime("%B %d, %Y")

Après avoir écrit ceci, exécutez ce qui suit :

python manage.py makemigrations
python manage.py migrate

Enregistrez ensuite le modèle dans core/admin.py comme nous l'avons fait auparavant avec le modèle Subscriber :

from django.contrib import admin
from .models import Subscriber
from .models import Newsletter

admin.site.register(Subscriber)
admin.site.register(Newsletter)

Vous pouvez désormais utiliser le tableau de bord d'administration pour télécharger des newsletters au format HTML. Vous pouvez créer ces newsletters HTML à l'aide de n'importe quel éditeur de texte, les enregistrer en tant que fichiers sur votre ordinateur pour les télécharger ensuite. Notez que le tableau de bord prend nativement en charge les téléchargements de fichiers ! Voici un exemple de newsletter (notez qu'il n'a pas besoin de balises <head> et <body> comme une page Web). Vous pouvez enregistrer les éléments suivants n'importe où sous test_email.html.

<p>Test Email</p>
<p>You are reading my email newsletter, and this is one of those newsletters!</p>

Capture d&#x27;écran Télécharger la newsletter

La dernière partie de ce projet consiste à envoyer les newsletters à toutes les adresses e-mail confirmées. Cette opération peut elle aussi être effectuée à partir du panneau d'administration en créant une action d'administration. Tout d'abord, nous allons écrire la fonction d'envoi en tant que méthode du modèle Newsletter dans core/models.py :

from django.db import models
from django.conf import settings
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

# Create your models here.
class Subscriber(models.Model):
    email = models.EmailField(unique=True)
    conf_num = models.CharField(max_length=15)
    confirmed = models.BooleanField(default=False)

    def __str__(self):
        return self.email + " (" + str(self.confirmed) + ")"

class Newsletter(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    subject = models.CharField(max_length=150)
    contents = models.FileField(upload_to='uploaded_newsletters/')

    def __str__(self):
        return self.subject + " " + self.created_at.strftime("%B %d, %Y")

    def send(self, request):
        contents = self.contents.read().decode('utf-8')
        subscribers = Subscriber.objects.filter(confirmed=True)
        sg = SendGridAPIClient(settings.SENDGRID_API_KEY)
        for sub in subscribers:
            message = Mail(
                    from_email=settings.FROM_EMAIL,
                    to_emails=sub.email,
                    subject=self.subject,
                    html_content=contents + (
                        '<br><a href="{}/delete/?email={}&conf_num={}">Unsubscribe</a>.').format(
                            request.build_absolute_uri('/delete/'),
                            sub.email,
                            sub.conf_num))
            sg.send(message)

Nous effectuons les opérations de lecture de fichier et de recherche dans la base de données d'abonnés une seule fois chacune, puis les répétons sur les abonnés confirmés afin de créer et d'envoyer l'e-mail à l'aide de l'API simple de SendGrid.

De plus, cette fonction peut être facilement appelée en tant qu'action d'administration dans core/admin.py :

from django.contrib import admin
from .models import Subscriber
from .models import Newsletter


def send_newsletter(modeladmin, request, queryset):
    for newsletter in queryset:
        newsletter.send(request)

send_newsletter.short_description = "Send selected Newsletters to all subscribers"


class NewsletterAdmin(admin.ModelAdmin):
    actions = [send_newsletter]

admin.site.register(Subscriber)
admin.site.register(Newsletter, NewsletterAdmin)

Les actions d'administration (dans notre cas, la fonction send_newsletter) ont une interface quelque peu maladroite, car elles nécessitent trois arguments de position (modeladmirequest et queryset), bien que dans notre cas nous n'ayons besoin que de deux d'entre eux, à savoir request pour construire l'URL absolue pour /delete/ et queryset, qui renvoie les newsletters sélectionnées, même si nous n'en envoyons probablement qu'une à la fois. Cela dit, revenir au panneau d'administration a pour effet d'ajouter cette fonction au menu déroulant sur la page http://127.0.0.1:8000/admin/core/newsletter/, ce qui est pratique car cela permet d'envoyer notre newsletter en quelques clics. Notez que le menu déroulant n'apparaît qu'une fois que vous avez une ou plusieurs newsletters dans la base de données. Avec ces fonctionnalités intégrées, nous avons évité des heures de travail liées à la configuration de nos propres formulaires et pages.

Capture d&#x27;écran de l&#x27;action d&#x27;administration Envoyer une newsletter

Affichage d'un tableau de bord

Dans notre liste de scénarios d'utilisation, nous avons indiqué que « l'administrateur doit pouvoir accéder à un tableau de bord pour afficher les abonnés et les e-mails envoyés ». Le tableau de bord d'administration fourni par Django permet à l'expéditeur d'afficher le nombre et la liste des abonnés, ainsi que de rédiger et d'envoyer des newsletters. Pour surveiller la diffusion des e-mails, rendez-vous sur le tableau de bord de votre compte SendGrid. Il est possible d'aller au bout de ce scénario sans code supplémentaire, même si l'une des limites du système est qu'il ne permet pas de savoir à quels abonnés une newsletter donnée a été envoyée.

 

Conclusion

Bien que l'on soit loin de la solution de newsletter e-mail complète, hébergée et gérée qu'offre Twilio SendGrid, nous avons développé les fonctionnalités de base en environ 2 500 mots sous la forme d'un projet Django pour débutants. L'interface d'administration extensible de Django facilite la construction d'applications complexes dont l'administration est restreinte, avec un minimum de codage et de configuration. L'API de messagerie de SendGrid nous permet d'envoyer des e-mails en quelques lignes de code, tout en assurant une distribution rapide et fiable.

Cela dit, même une application simple comme celle-ci nécessite de suivre un certain nombre d'étapes en termes de déploiement. Le déploiement avec Django nécessite de modifier sensiblement la configuration, y compris de changer la base de données (MySQL ou PostgreSQL au lieu de SQLite). J'espère toutefois avoir illustré la diversité des cas d'usage des technologies que nous avons abordées ici. Si vous souhaitez déployer cette application, consultez ce guide pour AWS ou celui-ci pour Digital Ocean.

Philip Kiely est développeur, auteur et entrepreneur. Il est étudiant de premier cycle au Grinnell College (promotion 2020). Vous pouvez retrouver son travail sur https://philipkiely.com et https://github.com/philipkiely, ou le contacter à l'adresse https://linkedin.com/in/philipkiely.