Ricerca…


Parametri

Classe / Metodo Il perché
UserProfile () Class La classe UserProfile estende il modello utente predefinito Django .
metodo create_profile () Il metodo create_profile () viene eseguito ogni volta che viene rilasciato un segnale post_save modello utente Django.

Osservazioni

Ora, i dettagli.

I segnali Django sono un modo per informare la tua app di determinati compiti (come un modello pre o post-salvataggio o eliminazione) quando ha luogo.

Questi segnali ti consentono di eseguire azioni a tua scelta immediatamente che il segnale viene rilasciato.

Ad esempio, ogni volta che viene creato un nuovo utente Django, il Modello utente rilascia un segnale, associando parametri come sender=User consente di indirizzare in modo specifico l'ascolto dei segnali a un'attività specifica che si verifica, in questo caso, una nuova creazione utente .

Nell'esempio precedente, l'intenzione è di creare un oggetto Profilo utente creato immediatamente dopo la creazione di un oggetto Utente. Pertanto, ascoltando specificamente un segnale post_save dal modello User (il modello utente Django predefinito), creiamo un oggetto UserProfile subito dopo la creazione di un nuovo User .

La documentazione di Django fornisce un'ampia documentazione su tutti i possibili segnali disponibili .

Tuttavia, l'esempio sopra riportato è quello di spiegare in termini pratici un tipico caso d'uso quando si usano i segnali come un'aggiunta utile.

"Con un grande potere viene una grande responsabilità". Può essere allettante avere segnali sparsi per l'intera app o progetto solo perché sono fantastici. Bene, non farlo. Perché sono cool non li rende la soluzione ideale per ogni situazione semplice che viene in mente.

I segnali sono ottimi, come al solito, non tutto. Login / Logout, i segnali sono fantastici. Modelli chiave che rilascino segnali, come il Modello utente, se disponibili.

La creazione di segnali per ogni modello della tua app può diventare travolgente a un certo punto e sconfiggere l'intera idea dell'uso sparring di Django Signals.

Non usare segnali quando (basato su Two Scoops of Django book ):

  • Il segnale si riferisce a un modello particolare e può essere spostato in uno dei metodi di quel modello, eventualmente chiamato da save() .
  • Il segnale può essere sostituito con un metodo di gestione modello personalizzato.
  • Il segnale si riferisce a una vista particolare e può essere spostato in quella vista

Potrebbe essere normale usare i segnali quando:

  • Il ricevitore del segnale deve apportare modifiche a più di un modello.
  • Vuoi inviare lo stesso segnale da più app e farle gestire allo stesso modo da un ricevitore comune.
  • Si desidera invalidare una cache dopo un salvataggio del modello.
  • Hai uno scenario insolito che richiede una richiamata e non c'è altro modo per gestirlo oltre a utilizzare un segnale. Ad esempio, si desidera attivare qualcosa in base al save() o init() del modello di un'app di terze parti. Non è possibile modificare il codice di terze parti ed estenderlo potrebbe essere impossibile, quindi un segnale fornisce un trigger per un callback.

Estensione dell'esempio del profilo utente

Questo esempio è uno snippet tratto dal profilo utente Django esteso come 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)

Sintassi diversa per postare / pre un segnale

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'):
        ...

Come trovare se si tratta di un inserimento o di un aggiornamento nel segnale pre_save

Utilizzando il pre_save possiamo determinare se un'azione di save sul nostro database riguardava l'aggiornamento di un oggetto esistente o la creazione di uno nuovo.

Per ottenere ciò è possibile controllare lo stato dell'oggetto modello:

    @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')

Ora ogni volta che viene eseguita un'azione di save , il segnale pre_save verrà eseguito e stamperà:

  • this is an update se l'azione deriva da un'azione di aggiornamento.
  • this is an insert se l'azione deriva da un'azione di inserimento.

Si noti che questo metodo non richiede query di database aggiuntive.

Ereditare i segnali sui modelli estesi

I segnali di Django sono limitati a precise firme di classe al momento della registrazione, e quindi i modelli sottoclasse non vengono immediatamente registrati sullo stesso segnale.

Prendi questo modello e segnala per esempio

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)

Con i modelli estesi, è necessario collegare manualmente il segnale su ciascuna sottoclasse altrimenti non verranno effettuati.

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

Con Python 3.6, puoi sfruttare alcuni metodi di classe aggiuntivi incorporati in classi per automatizzare questa associazione.

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow