Zoeken…


parameters

Klasse / Method Het waarom
UserProfile () Klasse De klasse UserProfile breidt het standaardgebruikersmodel van Django uit .
create_profile () methode De methode create_profile () wordt uitgevoerd wanneer een Django-gebruikersmodel post_save signaal wordt vrijgegeven .

Opmerkingen

Nu de details.

Django-signalen is een manier om uw app op de hoogte te stellen van bepaalde taken (zoals een model vóór of na het opslaan of verwijderen) wanneer dit plaatsvindt.

Met deze signalen kunt u acties van uw keuze uitvoeren zodra dat signaal wordt vrijgegeven.

Bijvoorbeeld, telkens wanneer een nieuwe Django-gebruiker wordt gemaakt, geeft het gebruikersmodel een signaal af, waarbij params zoals sender=User gekoppeld, zodat u specifiek kunt luisteren naar signalen op een specifieke activiteit die gebeurt, in dit geval een nieuwe gebruikerscreatie .

In het bovenstaande voorbeeld is het de bedoeling om een UserProfile-object te maken, direct nadat een User-object is gemaakt. Daarom, door post_save luisteren naar een post_save signaal van het User (het standaard Django-gebruikersmodel), creëren we een UserProfile object net nadat een nieuwe User is gemaakt.

De Django-documentatie biedt uitgebreide documentatie over alle mogelijke signalen die beschikbaar zijn .

Het bovenstaande voorbeeld is echter om in praktische termen een typisch gebruiksscenario uit te leggen wanneer het gebruik van signalen een nuttige toevoeging kan zijn.

"Met grote kracht, komt grote verantwoordelijkheid". Het kan verleidelijk zijn om signalen over je hele app of project te verspreiden, gewoon omdat ze geweldig zijn. Nou, niet doen. Omdat ze cool zijn, maken ze niet de oplossing voor elke eenvoudige situatie die te binnen schiet.

Signalen zijn geweldig voor, zoals gewoonlijk, niet voor alles. Inloggen / Afmelden, signalen zijn geweldig. Belangrijke modellen die tekens vrijgeven, zoals het gebruikersmodel, indien in orde.

Het creëren van signalen voor elk model in uw app kan op een gegeven moment overweldigend worden en het hele idee van het sparring-gebruik van Django-signalen verslaan.

Gebruik geen signalen wanneer (gebaseerd op Two Scoops of Django-boek ):

  • Het signaal heeft betrekking op een bepaald model en kan worden verplaatst naar een van de methoden van dat model, mogelijk aangeroepen door save() .
  • Het signaal kan worden vervangen door een aangepaste modelmanagermethode.
  • Het signaal heeft betrekking op een bepaald aanzicht en kan naar dat aanzicht worden verplaatst

Het kan goed zijn om signalen te gebruiken wanneer:

  • Uw signaalontvanger moet wijzigingen aanbrengen in meer dan één model.
  • U wilt hetzelfde signaal van meerdere apps verzenden en ze op dezelfde manier laten behandelen door een gemeenschappelijke ontvanger.
  • U wilt een cache ongeldig maken nadat een model is opgeslagen.
  • U hebt een ongewoon scenario dat moet worden teruggebeld en er is geen andere manier om dit aan te pakken dan een signaal te gebruiken. U wilt bijvoorbeeld iets activeren op basis van de save() of init() van het app-model van een derde. U kunt de code van derden niet wijzigen en het kan onmogelijk zijn om deze uit te breiden, dus een signaal geeft een trigger voor een callback.

Voorbeeld van gebruikersprofiel uitbreiden

Dit voorbeeld is een fragment uit het Extending Django-gebruikersprofiel als een professional

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)

Verschillende syntaxis om een signaal te plaatsen / vooraf te gaan

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

Hoe te zien of het een insert of update is in het pre_save-signaal

Door gebruik te maken van de pre_save kunnen we bepalen of een save actie op onze database was over het bijwerken van een bestaand object of een nieuwe te maken.

Om dit te bereiken kunt u de status van het modelobject controleren:

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

Nu elke keer dat een save handeling plaatsvindt, het pre_save zal signaal lopen en zal worden afgedrukt:

  • this is an update als de actie is afgeleid van een updateactie.
  • this is an insert als de actie is afgeleid van een invoegactie.

Merk op dat deze methode geen extra databasequery's vereist.

Overerving van signalen op uitgebreide modellen

De signalen van Django zijn beperkt tot precieze klassehandtekeningen bij registratie, en dus worden subklasse modellen niet onmiddellijk geregistreerd op hetzelfde signaal.

Neem dit model en signaal bijvoorbeeld

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)

Bij uitgebreide modellen moet u het signaal handmatig op elke subklasse aansluiten, anders worden ze niet beïnvloed.

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

Met Python 3.6 kunt u een aantal aanvullende klassenmethoden gebruiken die in klassen zijn ingebouwd om deze binding te automatiseren.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow