Système de suivi de contacts avec Django

14 février 2024

logo django


Mise en place d'un suivi des demandes envoyées par les utilisateurs. Dans cet article, nous partons d'un simple formulaire de contact et d'un modèle permettant de suivre les demandes des utilisateurs.


Introduction

Cet article peut-être considéré comme une variante de l'article précédent : Création d'un système de Tickets/SAV simple (Django).


Honnêtement, je mets souvent en place une application dédiée au suivi des contacts.

À la base de mon système de suivi, je déploie un formulaire. Selon les applications, ce formulaire est personnalisé en fonction de la connexion de l'utilisateur.

Pour cet article, nous allons partir d'un formulaire de contact basique.

Le formulaire de contact

from django import forms
from django_recaptcha.fields import ReCaptchaField


class ContactForm(forms.Form):
    email = forms.EmailField(label="Email")
    subject = forms.CharField(label="Objet", max_length=100)
    text = forms.CharField(label="message", max_length=2000, widget=forms.Textarea)
    security = ReCaptchaField(label="Sécurité")

Le formulaire va nous permettre de récupérer l'e-mail, le sujet et le message en question. Très simple.

Dans la vue, nous allons récupérer les informations qui ont été envoyées dans le corps de la requête.

La vue

def contact_view(request):
    user = request.user

    if request.method == "POST":
        form = ContactForm(request.POST)
        if form.is_valid():
            email = form.cleaned_data["email"]
            subject = form.cleaned_data["subject"]
            text = form.cleaned_data["text"]
            Contact.objects.create(email=email, subject=subject, message=text)
            try:
                send_mail(subject=subject, message=f"De la part de {email} - {text}",
                          recipient_list=["mon_adresse@gmail.com"], from_email=None)
                send_mail(subject="Email bien envoyé", message="J'ai bien reçu votre email, je réponds rapidement :).",
                          from_email=None, recipient_list=[email])
            except SMTPException:
                pass # Add a logging
            messages.add_message(request, messages.INFO,
                                 "Le message a été envoyé, si vous ne recevez pas d'email "
                                 "de confirmation veuillez vérifier vos spams ou renvoyer votre "
                                 "message en vérifiant bien l'email renseigné svp.")
            return redirect("sav:contact")
    else:
        form = ContactForm(initial={"email": user.email}) if user.is_authenticated else ContactForm()

    return render(request, "sav/contact.html", context={"form": form})

Plusieurs choses ici, dont un Contact qui sort de nulle part... Je vais y venir. À part ça, c'est assez basique : avec une méthode GET, j'affiche le formulaire, et si l'utilisateur est connecté, j'envoie son e-mail en donnée initiale.

Dans le cadre d'une méthode POST, je récupère les informations envoyées via le formulaire pour :

  • M'envoyer un e-mail avec toutes les informations,
  • Envoyer un e-mail d'accusé de réception à l'utilisateur.

Si un problème survient avec l'envoi des e-mails, vous pouvez mettre en place un système de logging.

# Extrait de la vue
            try:
                send_mail(subject=subject, message=f"De la part de {email} - {text}",
                          recipient_list=["mon_email@gmail.com"], from_email=None)
                send_mail(subject="Email bien envoyé", message="J'ai bien reçu votre email, je réponds rapidement :).",
                          from_email=None, recipient_list=[email])
            except SMTPException:
                pass # Add a logging

Mais avant le bloc try-except avec l'envoi des e-mails, vous avez sûrement remarqué le :

Contact.objects.create(email=email, subject=subject, message=text)

Ajout d'un modèle Contact

Dans ma vue de contact, je crée une instance de la classe Contact afin d'avoir une meilleure traçabilité des demandes.

Mais surtout, si un problème survient avec l'envoi de l'e-mail, dans tous les cas, une instance de Contact est enregistrée dans la base de données.

class Contact(models.Model):
    email = models.EmailField()
    subject = models.CharField(max_length=100, verbose_name="Objet")
    message = models.CharField(max_length=2000)
    date = models.DateTimeField(auto_now_add=True)
    done = models.BooleanField(default=False, verbose_name="Traité")

    def get_user(self):
        try:
            return CustomUser.objects.get(email=self.email)
        except ObjectDoesNotExist:
            return "Pas de compte utilisateur trouvé"

On y retrouve toutes les informations nécessaires envoyées par l'utilisateur : email, sujet, message et la date.

Dans mon exemple, j'y ai ajouté un booléen "done", ainsi l'administrateur peut marquer comme traitées les demandes.

En images, une vue depuis l’administration avec les demandes envoyées par les utilisateurs :

Administration système de SAV

Lorsque je clique sur la demande :

message sav

Conclusion

L'idée ici est de faire d'une pierre deux coups (j'adore cette expression).

Un e-mail est envoyé, mais dans tous les cas une instance de Contact basée sur les informations de l'e-mail est sauvegardée.

  • Cela permet un meilleur suivi des demandes,
  • En cas de problème d'envoi, l'administrateur est quand même informé de la demande envoyée par l'utilisateur.

Retour