Django
signalen
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()
ofinit()
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)