Maison >développement back-end >Tutoriel Python >Construire un système de notification flexible dans Django : un guide complet

Construire un système de notification flexible dans Django : un guide complet

Patricia Arquette
Patricia Arquetteoriginal
2024-12-01 15:43:09905parcourir

Building a Flexible Notification System in Django: A Comprehensive Guide

Les notifications sont un élément clé de toute application Web moderne, garantissant que les utilisateurs sont informés et engagés. Un système de notification bien mis en œuvre peut gérer plusieurs canaux tels que les alertes dans l'application, les e-mails et les SMS tout en adaptant dynamiquement le contenu pour une expérience utilisateur transparente. Dans ce guide, nous vous expliquerons comment créer un système de notification robuste et évolutif dans Django.


Fonctionnalités du système

Notre système de notification est conçu pour fournir :

  1. Prise en charge de plusieurs canaux : notifications via des alertes intégrées à l'application, par e-mail ou par SMS.
  2. Personnalisation dynamique du contenu : modèles avec espaces réservés pour générer des messages personnalisés.
  3. Déclencheurs basés sur des événements : déclenchez des notifications basées sur des événements système ou utilisateur spécifiques.
  4. Suivi du statut : surveillez l'état de livraison pour les notifications par e-mail et SMS.
  5. Administrateur et intégration du système : les notifications peuvent être déclenchées par les administrateurs ou par des événements système.

Définir les modèles

1. Modèles de notifications

Les modèles constituent l'épine dorsale de notre système, stockant du contenu réutilisable pour les notifications.

from django.db import models

class ChannelType(models.TextChoices):
    APP = 'APP', 'In-App Notification'
    SMS = 'SMS', 'SMS'
    EMAIL = 'EMAIL', 'Email'


class TriggeredByType(models.TextChoices):
    SYSTEM = 'SYSTEM', 'System Notification'
    ADMIN = 'ADMIN', 'Admin Notification'


class TriggerEvent(models.TextChoices):
    ENROLLMENT = 'ENROLLMENT', 'Enrollment'
    ANNOUNCEMENT = 'ANNOUNCEMENT', 'Announcement'
    PROMOTIONAL = 'PROMOTIONAL', 'Promotional'
    RESET_PASSWORD = 'RESET_PASSWORD', 'Reset Password'

class NotificationTemplate(models.Model):
    title = models.CharField(max_length=255)
    template = models.TextField(help_text='Use placeholders like {{username}} for personalization.')
    channel = models.CharField(max_length=20, choices=ChannelType.choices, default=ChannelType.APP)
    triggered_by = models.CharField(max_length=20, choices=TriggeredByType.choices, default=TriggeredByType.SYSTEM)
    trigger_event = models.CharField(max_length=50, choices=TriggerEvent.choices, help_text='Event that triggers this template.')
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

Caractéristiques principales :

  • modèle : texte avec des espaces réservés pour les valeurs dynamiques telles que {{username}}.
  • canal : spécifie s'il s'agit d'un e-mail, d'un SMS ou d'une notification dans l'application.
  • trigger_event : associe le modèle à un événement spécifique.

2. Notifications générales

Le modèle de notification relie les modèles aux utilisateurs et stocke toute charge utile dynamique à des fins de personnalisation.

class Notification(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="notifications")
    content = models.ForeignKey(NotificationTemplate, on_delete=models.CASCADE, related_name="notifications")
    payload = models.JSONField(default=dict, help_text="Data to replace template placeholders.")
    is_read = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

3. Modèles spécifiques à une chaîne

Pour gérer les emails et SMS de manière unique, nous définissons des modèles spécifiques.

Notifications par e-mail

Ce modèle gère les données spécifiques aux e-mails, telles que la génération dynamique de messages et le suivi de la livraison.

class StatusType(models.TextChoices):
    PENDING = 'PENDING', 'Pending'
    SUCCESS = 'SUCCESS', 'Success'
    FAILED = 'FAILED', 'Failed'

class EmailNotification(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='email_notifications')
    content = models.ForeignKey(NotificationTemplate, on_delete=models.CASCADE, related_name='email_notifications')
    payload = models.JSONField(default=dict)
    status = models.CharField(max_length=20, choices=StatusType.choices, default=StatusType.PENDING)
    status_reason = models.TextField(null=True)

    @property
    def email_content(self):
        """
        Populate the template with dynamic data from the payload.
        """
        content = self.content.template
        for key, value in self.payload.items():
            content = re.sub(
                rf"{{{{\s*{key}\s*}}}}",
                str(value),
                content,
            )
        return content

Notifications SMS

Semblable aux notifications par e-mail, une logique spécifique aux SMS est implémentée ici.

class SMSNotification(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sms_notifications')
    content = models.ForeignKey(NotificationTemplate, on_delete=models.CASCADE, related_name='sms_notifications')
    payload = models.JSONField(default=dict)
    status = models.CharField(max_length=20, choices=StatusType.choices, default=StatusType.PENDING)
    status_reason = models.TextField(null=True)

    @property
    def sms_content(self):
        """
        Populate the template with dynamic data from the payload.
        """
        content = self.content.template
        for key, value in self.payload.items():
            content = re.sub(
                rf"{{{{\s*{key}\s*}}}}",
                str(value),
                content,
            )
        return content

Intégration administrateur

Pour faciliter la gestion des notifications, nous enregistrons les modèles dans le panneau d'administration de Django.

from django.contrib import admin
from notifier.models import NotificationTemplate

@admin.register(NotificationTemplate)
class NotificationTemplateAdmin(admin.ModelAdmin):
    list_display = ['title', 'channel', 'triggered_by', 'trigger_event', 'is_active']
    list_filter = ['channel', 'triggered_by', 'is_active']
    search_fields = ['title', 'trigger_event']

Service de notifications

Nous mettrons en œuvre une couche de service pour gérer l'envoi de notifications via différents canaux.

Modèle de stratégie

À l'aide du modèle de stratégie, nous définirons des classes pour chaque canal de notification.

from django.db import models

class ChannelType(models.TextChoices):
    APP = 'APP', 'In-App Notification'
    SMS = 'SMS', 'SMS'
    EMAIL = 'EMAIL', 'Email'


class TriggeredByType(models.TextChoices):
    SYSTEM = 'SYSTEM', 'System Notification'
    ADMIN = 'ADMIN', 'Admin Notification'


class TriggerEvent(models.TextChoices):
    ENROLLMENT = 'ENROLLMENT', 'Enrollment'
    ANNOUNCEMENT = 'ANNOUNCEMENT', 'Announcement'
    PROMOTIONAL = 'PROMOTIONAL', 'Promotional'
    RESET_PASSWORD = 'RESET_PASSWORD', 'Reset Password'

class NotificationTemplate(models.Model):
    title = models.CharField(max_length=255)
    template = models.TextField(help_text='Use placeholders like {{username}} for personalization.')
    channel = models.CharField(max_length=20, choices=ChannelType.choices, default=ChannelType.APP)
    triggered_by = models.CharField(max_length=20, choices=TriggeredByType.choices, default=TriggeredByType.SYSTEM)
    trigger_event = models.CharField(max_length=50, choices=TriggerEvent.choices, help_text='Event that triggers this template.')
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

Service de notifications

Ce service relie tout ensemble, sélectionnant la stratégie appropriée en fonction du canal de notification.

class Notification(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="notifications")
    content = models.ForeignKey(NotificationTemplate, on_delete=models.CASCADE, related_name="notifications")
    payload = models.JSONField(default=dict, help_text="Data to replace template placeholders.")
    is_read = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

Exemple d'utilisation

Voici comment utiliser le service de notification :

class StatusType(models.TextChoices):
    PENDING = 'PENDING', 'Pending'
    SUCCESS = 'SUCCESS', 'Success'
    FAILED = 'FAILED', 'Failed'

class EmailNotification(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='email_notifications')
    content = models.ForeignKey(NotificationTemplate, on_delete=models.CASCADE, related_name='email_notifications')
    payload = models.JSONField(default=dict)
    status = models.CharField(max_length=20, choices=StatusType.choices, default=StatusType.PENDING)
    status_reason = models.TextField(null=True)

    @property
    def email_content(self):
        """
        Populate the template with dynamic data from the payload.
        """
        content = self.content.template
        for key, value in self.payload.items():
            content = re.sub(
                rf"{{{{\s*{key}\s*}}}}",
                str(value),
                content,
            )
        return content

Si vous avez trouvé ce guide utile et perspicace, n'oubliez pas d'aimer et de suivre pour plus de contenu comme celui-ci. Votre soutien me motive à partager des implémentations plus pratiques et des tutoriels approfondis. Continuons à créer des applications étonnantes ensemble !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn