Recherche…


Paramètres

Classe / méthode Le pourquoi
Classe UserProfile () La classe UserProfile étend le modèle d'utilisateur par défaut de Django .
Méthode create_profile () La méthode create_profile () est exécutée chaque fois qu'un signal post_save modèle d'utilisateur Django est libéré .

Remarques

Maintenant, les détails.

Les signaux de Django sont un moyen d'informer votre application de certaines tâches (telles qu'un modèle avant ou après la sauvegarde ou la suppression) lorsqu'elles ont lieu.

Ces signaux vous permettent d'effectuer des actions de votre choix immédiatement après la sortie du signal.

Par exemple, chaque fois qu'un nouvel utilisateur Django est créé, le modèle utilisateur libère un signal, en associant des paramètres tels que sender=User vous permettant de cibler spécifiquement votre écoute de signaux vers une activité spécifique, dans ce cas, une nouvelle création d'utilisateur. .

Dans l'exemple ci-dessus, l'intention est de créer un objet UserProfile immédiatement après la création d'un objet User. Par conséquent, en écoutant un signal post_save à partir du modèle User (le modèle utilisateur Django par défaut), nous créons un objet UserProfile juste après la création d'un nouvel User .

La documentation de Django fournit une documentation complète sur tous les signaux possibles disponibles .

Toutefois, l’exemple ci-dessus explique en termes pratiques un cas d’utilisation typique lorsqu’on utilise les signaux peut être un ajout utile.

"Un grand pouvoir implique de grandes responsabilités". Il peut être tentant d'avoir des signaux dispersés dans toute votre application ou projet, simplement parce qu'ils sont géniaux. Eh bien non. Parce qu'ils sont cool, ils ne sont pas la solution idéale pour toutes les situations simples qui leur viennent à l'esprit.

Les signaux sont parfaits pour, comme d'habitude, pas tout. Login / Logouts, les signaux sont excellents. Les modèles clés libèrent des signes, comme le modèle utilisateur, si cela convient.

La création de signaux pour chaque modèle de votre application peut être écrasante à un moment donné et faire échec à l’idée générale de l’utilisation des signaux Django.

N'utilisez pas de signaux lorsque (basé sur le livre Two Scoops of Django ):

  • Le signal se rapporte à un modèle particulier et peut être déplacé dans l'une des méthodes de ce modèle, éventuellement appelée par save() .
  • Le signal peut être remplacé par une méthode de gestionnaire de modèles personnalisée.
  • Le signal se rapporte à une vue particulière et peut être déplacé dans cette vue

Il peut être correct d'utiliser des signaux lorsque:

  • Votre récepteur de signal doit apporter des modifications à plusieurs modèles.
  • Vous souhaitez envoyer le même signal depuis plusieurs applications et les faire traiter de la même manière par un récepteur commun.
  • Vous souhaitez invalider un cache après une sauvegarde de modèle.
  • Vous avez un scénario inhabituel qui nécessite un rappel, et il n'y a pas d'autre moyen de le gérer que d'utiliser un signal. Par exemple, vous voulez déclencher quelque chose en fonction de save() ou init() du modèle d'une application tierce. Vous ne pouvez pas modifier le code tiers et l'étendre peut être impossible. Un signal déclenche donc un rappel.

Extension de l'exemple de profil utilisateur

Cet exemple est un extrait tiré du profil utilisateur Extending Django comme un pro

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
 
class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='user')
    website = models.URLField(default='', blank=True)
    bio = models.TextField(default='', blank=True)

def create_profile(sender, **kwargs):
    user = kwargs["instance"]
    if kwargs["created"]:
        user_profile = UserProfile(user=user)
        user_profile.save()
post_save.connect(create_profile, sender=User)

Syntaxe différente pour poster / pré-signaler

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
 
class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='user')
    website = models.URLField(default='', blank=True)
    bio = models.TextField(default='', blank=True)

@receiver(post_save, sender=UserProfile)
def post_save_user(sender, **kwargs):
    user = kwargs.get('instance')
    if kwargs.get('created'):
        ...

Comment trouver s'il s'agit d'une insertion ou d'une mise à jour dans le signal pre_save

En utilisant pre_save nous pouvons déterminer si une action de save sur notre base de données consistait à mettre à jour un objet existant ou à en créer un nouveau.

Pour ce faire, vous pouvez vérifier l'état de l'objet du modèle:

    @receiver(pre_save, sender=User)
    def pre_save_user(sender, instance, **kwargs): 
        if not instance._state.adding:
            print ('this is an update')
        else:
            print ('this is an insert')

Maintenant, chaque fois qu'une action de save a lieu, le signal pre_save sera exécuté et imprimera:

  • this is an update si l'action dérive d'une action de mise à jour.
  • this is an insert si l'action dérive d'une action d'insertion.

Notez que cette méthode ne nécessite aucune requête de base de données supplémentaire.

Héritage des signaux sur les modèles étendus

Les signaux de Django sont limités à des signatures de classe précises lors de l'enregistrement, et les modèles sous-classés ne sont donc pas immédiatement enregistrés sur le même signal.

Prenez ce modèle et signalez par exemple

class Event(models.Model):
    user = models.ForeignKey(User)


class StatusChange(Event):
    ...


class Comment(Event):
    ...


def send_activity_notification(sender, instance: Event, raw: bool, **kwargs):
    """
    Fire a notification upon saving an event
    """

    if not raw:
        msg_factory = MessageFactory(instance.id)
        msg_factory.on_activity(str(instance))
post_save.connect(send_activity_notification, Event)

Avec les modèles étendus, vous devez attacher manuellement le signal sur chaque sous-classe, sinon ils ne seront pas effectués.

post_save.connect(send_activity_notification, StatusChange)
post_save.connect(send_activity_notification, Comment)

Avec Python 3.6, vous pouvez tirer parti de certaines méthodes de classe supplémentaires intégrées aux classes pour automatiser cette liaison.

class Event(models.Model):

    @classmethod
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        post_save.connect(send_activity_notification, cls)


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow